Cod sursa(job #2409708)

Utilizator robx12lnLinca Robert robx12ln Data 19 aprilie 2019 12:48:00
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.7 kb
#include<bits/stdc++.h>
using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

const int DIM = 1e5 + 5;

int Wh_Path[DIM], N, M, S[DIM], arr[DIM], Pos_Path[DIM], K, ans;
int Niv[DIM], T[DIM];
vector<int> Path[DIM], Aint_Path[DIM], edge[DIM];

void dfs( int nod, int nv ){
    S[nod] = 1;
    Niv[nod] = nv;
    bool ok = false;
    for( int i = 0; i < edge[nod].size(); i++ ){
        if( edge[nod][i] != T[nod] ){
            ok = true;
            T[ edge[nod][i] ] = nod;
            dfs( edge[nod][i], nv + 1 );
            S[nod] += S[ edge[nod][i] ];
        }
    }
    if( ok == false ){
        K++;
        Path[K].push_back( nod );
        Wh_Path[nod] = K;
        Pos_Path[nod] = Path[K].size();
    }else{
        int mx = 0, x = -1;
        for( int i = 0; i < edge[nod].size(); i++ ){
            if( edge[nod][i] == T[nod] )
                continue;
            if( mx < S[ edge[nod][i] ] )
                mx = S[ edge[nod][i] ], x = edge[nod][i];
        }
        Path[ Wh_Path[x] ].push_back( nod );
        Wh_Path[nod] = Wh_Path[x];
        Pos_Path[nod] = Path[ Wh_Path[x] ].size();
    }
}

void build_aint( int k, int nod, int st, int dr ){
    if( st == dr ){
        Aint_Path[k][nod] = arr[ Path[k][st - 1] ];
    }else{
        int mid = ( st + dr ) >> 1;
        build_aint( k, (nod<<1)^0, st, mid + 0 );
        build_aint( k, (nod<<1)|1, mid + 1, dr );
        Aint_Path[k][nod] = max( Aint_Path[k][(nod<<1)^0], Aint_Path[k][(nod<<1)|1] );
    }
}

void update_aint( int k, int nod, int st, int dr, int p, int x ){
    if( st == dr ){
        Aint_Path[k][nod] = x;
    }else{
        int mid = ( st + dr ) >> 1;
        if( p <= mid )
            update_aint( k, (nod<<1)^0, st, mid + 0, p, x );
        else
            update_aint( k, (nod<<1)|1, mid + 1, dr, p, x );
        Aint_Path[k][nod] = max( Aint_Path[k][(nod<<1)^0], Aint_Path[k][(nod<<1)|1] );
    }
}

void query_aint( int k, int nod, int st, int dr, int a, int b ){
    if( a <= st && dr <= b ){
        ans = max( ans, Aint_Path[k][nod] );
    }else{
        int mid = ( st + dr ) >> 1;
        if( a <= mid )
            query_aint( k, (nod<<1)^0, st, mid + 0, a, b );
        if( b > mid )
            query_aint( k, (nod<<1)|1, mid + 1, dr, a, b );
    }
}

void solve_query( int x, int y ){
    ans = 0;
    while( Wh_Path[x] != Wh_Path[y] ){
        if( Niv[ T[ Path[ Wh_Path[x] ].back() ] ] > Niv[ T[ Path[ Wh_Path[y] ].back() ] ] ){
            query_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], Path[ Wh_Path[x] ].size() );
            x = T[ Path[ Wh_Path[x] ].back() ];
        }else{
            query_aint( Wh_Path[y], 1, 1, Path[ Wh_Path[y] ].size(), Pos_Path[y], Path[ Wh_Path[y] ].size() );
            y = T[ Path[ Wh_Path[y] ].back() ];
        }
    }
    if( Pos_Path[x] > Pos_Path[y] )
        swap(x, y);
    query_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], Pos_Path[y] );
}

int main(){

    fin >> N >> M;
    for( int i = 1; i <= N; i++ )
        fin >> arr[i];

    for( int i = 1; i < N; i++ ){
        int x, y; fin >> x >> y;
        edge[x].push_back( y );
        edge[y].push_back( x );
    }

    dfs( 1, 1 );
    for( int i = 1; i <= K; i++ ){
        Aint_Path[i].resize( (int)(4 * Path[i].size()), 0 );
        build_aint( i, 1, 1, Path[i].size() );
    }

    for( int i = 1; i <= M; i++ ){
        int t, x, y; fin >> t >> x >> y;
        if( t == 0 ){
            update_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], y );
        }else{
            solve_query( x, y );
            fout << ans << "\n";
        }
    }

    return 0;
}