Cod sursa(job #1234764)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 27 septembrie 2014 23:07:50
Problema Heavy Path Decomposition Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 5.65 kb
#include <bits/stdc++.h>

#define VI vector<int>
#define VII vector<pair<int,int>>
#define QI queue<int>

#define ms(a,v) memset( a, v, sizeof( a ) )
#define FOR(i,a,b) for(int i = a; i <= b; ++i)
#define ROF(i,a,b) for(int i = a; i >= b; i--)
#define foreach(v, c) for( typeof( (c).begin() ) v = (c).begin(); v != (c).end(); ++v)

#define pb push_back
#define pp pair<int,int>
#define mp make_pair
#define fi first
#define se second

#define popcount __builtin_popcount
#define gcd __gcd
#define bit(n,i) ( n & ( 1LL << i ) )
#define lsb(x) ( x & ( -x ) )

#define FIN(str) freopen(str,"r",stdin)
#define FOUT(str) freopen(str,"w",stdout)
#define Fin(str) ifstream(str)
#define Fout(str) ostream(str)
#define SYNC ios_base::sync_with_stdio(0);

#define ll long long
#define ull unsigned long long

inline void read( int &a )
{
    register char ch;
    a = 0;
    int sign = 1;

    do
    {
        ch = getchar();

    } while ( !isdigit( ch ) && ch != '-' );

    if ( ch == '-' )
    {
        sign = -1;
        ch = getchar();
    }

    do
    {
        a = a * 10 + ch - '0';
        ch = getchar();

    } while( isdigit( ch ) );

    a *= sign;
}

inline void write( int a )
{
    char s[20];
    int i = 0;
    int sign = 1;

    if ( a < 0 )
        sign = -1,
        a = -a;

    do
    {
        s[ i++ ] = a % 10 + '0';
        a /= 10;

    } while ( a );

    i--;

    if ( sign == -1 )
        putchar( '-' );

    while ( i >= 0 ) putchar( s[ i-- ] );
}

const int dx[] = { -1, 0, 1, 0 };
const int dy[] = { 0, 1, 0, -1 };

const int dl[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dc[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

const int INF = 2e9;
const double EPS = 1e-9;

const int Nmax = 1e5 + 2;

const int LgMax = log2(Nmax) + 1;

using namespace std;

int Left[Nmax], Right[Nmax], Parent[Nmax], Cost[Nmax], Maxim[Nmax];
int Revert[Nmax];

void lazy( int x )
{
    if ( Revert[x] )
    {
        Revert[x] = 0;
        swap( Left[x], Right[x] );

        if ( Left[x] != 0 ) Revert[ Left[x] ] ^= 1;
        if ( Right[x] != 0 ) Revert[ Right[x] ] ^= 1;
    }
}

void update( int p )
{
    Maxim[p] = Cost[p];
    if ( Left[p] ) Maxim[p] = max( Maxim[p], Maxim[ Left[p] ] );
    if ( Right[p] ) Maxim[p] = max( Maxim[p], Maxim[ Right[p] ] );
}

bool isRoot( int p )
{
    return ( !Parent[p] || ( Left[ Parent[p] ] != p && Right[ Parent[p] ] != p ) );
}

void Zig( int p )
{
    int q = Parent[p];
    int r = Parent[q];

    if ( ( Left[q] = Right[p] ) != 0 )
        Parent[ Left[q] ] = q;

    Right[p] = q;
    Parent[q] = p;

    if ( ( Parent[p] = r ) != 0 )
    {
        if ( Left[r] == q )
            Left[r] = p;
        else
            if ( Right[r] == q )
                Right[r] = p;
    }

    update( q );
}

void Zag( int p )
{
    int q = Parent[p];
    int r = Parent[q];

    if ( ( Right[q] = Left[p] ) != 0 )
        Parent[ Right[q] ] = q;

    Left[p] = q;
    Parent[q] = p;

    if ( ( Parent[p] = r ) != 0 )
    {
        if ( Left[r] == q )
            Left[r] = p;
        else
            if ( Right[r] == q )
                Right[r] = p;
    }

    update( q );
}

void splay( int p )
{
    while ( !isRoot( p ) )
    {
        int q = Parent[p];
        int r = Parent[q];

        if ( isRoot( q ) )
        {
            lazy( q );
            lazy( p );

            if ( Left[q] == p )
                Zig( p );
            else
                Zag( p );
        }
        else
        {
            lazy( r );
            lazy( q );
            lazy( p );

            if ( ( p == Left[q] ) == ( q == Left[r] ) )
            {
                if ( p == Left[q] )
                {
                    Zig( q );
                    Zig( p );
                }
                else
                {
                    Zag( q );
                    Zag( p );
                }
            }
            else
            {
                if ( p == Left[q] )
                    Zig( p );
                else
                    Zag( p );

                if ( p == Left[r] )
                    Zig( p );
                else
                    Zag( p );
            }
        }
    }

    lazy( p );
    update( p );
}

int expose( int p )
{
    int last = 0;

    for ( int x = p; x != 0; x = Parent[x] )
    {
        splay( x );
        Left[x] = last;
        last = x;
    }

    splay( p );

    return last;
}

void makeroot( int p )
{
    expose( p );
    Revert[p] ^= 1;
}

int findRoot( int p )
{
    expose( p );

    while ( Right[p] != 0 ) p = Right[p];

    return p;
}

void link( int x, int y )
{
    makeroot( x );
    Parent[x] = y;
}

void cut( int x )
{
    expose( x );
    Parent[ Right[x] ] = 0;
    Right[x] = 0;
}

int query( int x, int y )
{
    makeroot( x );
    expose( y );

    return Maxim[y];
}

void updateNode( int x, int value )
{
    makeroot( x );
    expose( x );
    Cost[x] = Maxim[x] = value;
}

vector <int> G[Nmax];
int tata[Nmax];
int N, Q;

void DFS( int nod )
{
    for ( auto x: G[nod] )
    {
        if ( !tata[x] )
        {
            tata[x] = nod;
            link( x, nod );
            DFS( x );
        }
    }
}

int main()
{
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");

    in.sync_with_stdio( false );

    in >> N >> Q;

    for ( int i = 1; i <= N; ++i )
    {
        in >> Cost[i];
        Maxim[i] = Cost[i];
    }

    for ( int i = 1, a, b; i < N; ++i )
    {
        in >> a >> b;

        G[a].push_back( b );
        G[b].push_back( a );
    }

    tata[1] = 1;
    DFS( 1 );

    for ( int i = 1, tip, a, b; i <= Q; ++i )
    {
        in >> tip >> a >> b;

        if ( tip == 0 )
        {
            updateNode( a, b );
        }
        else
        {
            out << query( a, b ) << "\n";
        }
    }

    return 0;
}