Cod sursa(job #2409664)

Utilizator robx12lnLinca Robert robx12ln Data 19 aprilie 2019 12:35:09
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.29 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], Rmq[19][DIM], Log;
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] != Rmq[0][nod] ){
            ok = true;
            Rmq[0][ 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] == Rmq[0][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] );
    }
}

inline int lca( int x, int y ){
    if( Niv[x] > Niv[y] )
        swap( x, y );
    for( int k = Log; k >= 0; k-- )
        if( Niv[ Rmq[k][y] ] >= Niv[x] )
            y = Rmq[k][y];
    if( x == y )
        return x;
    for( int k = Log; k >= 0; k-- ){
        if( Rmq[k][x] != Rmq[k][y] ){
            x = Rmq[k][x];
            y = Rmq[k][y];
        }
    }
    if( x == y )
        return x;
    return Rmq[0][x];
}

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 ){
    int z = lca( x, y );
    ans = 0;
    while( Wh_Path[x] != Wh_Path[z] ){
        query_aint( Wh_Path[x], 1, 1, Path[ Wh_Path[x] ].size(), Pos_Path[x], Path[ Wh_Path[x] ].size() );
        x = Rmq[0][ Path[ Wh_Path[x] ].back() ];
    }
    while( Wh_Path[y] != Wh_Path[z] ){
        query_aint( Wh_Path[y], 1, 1, Path[ Wh_Path[y] ].size(), Pos_Path[y], Path[ Wh_Path[y] ].size() );
        y = Rmq[0][ 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 );

    Log = 0;
    while( (1<<Log) <= N )
        Log++;
    for( int k = 1; k <= Log; k++ )
        for( int i = 1; i <= N; i++ )
            Rmq[k][i] = Rmq[k - 1][ Rmq[k - 1][i] ];

    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;
}