Cod sursa(job #2300002)

Utilizator robx12lnLinca Robert robx12ln Data 10 decembrie 2018 18:47:20
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.23 kb
#include<bits/stdc++.h>
using namespace std;

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

const int DIM = 1e5 + 5;

int N, M, Pos[DIM], Father_Path[DIM], S[DIM], V[DIM], Ind, Wh_Path[DIM], Lvl[DIM];
vector<int> Aint_Path[DIM], Path[DIM], edge[DIM];

void dfs( int nod, int tata ){

    S[nod] = 1;

    int link_nod = -1, maxs = 0;

    for( int i = 0; i < edge[nod].size(); i++ ){
        int son = edge[nod][i];

        if( son != tata ){
            Lvl[son] = Lvl[nod] + 1;
            dfs( son, nod );
            S[nod] += S[son];
            if( maxs < S[son] )
                maxs = S[son], link_nod = son;
        }

    }

    if( link_nod == -1 ){
        Wh_Path[nod] = ++Ind;
        Path[Ind].push_back( nod );
        return;
    }

    Wh_Path[nod] = Wh_Path[link_nod];
    Path[ Wh_Path[nod] ].push_back( nod );
    for( int i = 0; i < edge[nod].size(); i++ ){
        int son = edge[nod][i];
        if( son != tata && son != link_nod )
            Father_Path[ Wh_Path[son] ] = nod;
    }

    return;

}

void debug1(){
    fout << Ind << "\n";
    for( int i = 1; i <= Ind; i++ ){
        fout << "Father of path is :" << Father_Path[i] << "\n";
        fout << "Nodes of path are :";
        reverse( Path[i].begin(), Path[i].end() );
        for( int j = 0; j < Path[i].size(); j++ )
            fout << Path[i][j] << " ";
        fout << "\n\n";

    }
}

void build( int k, int nod, int st, int dr ){

    int Nst = (nod<<1);
    int Ndr = ((nod<<1)|1);

    if( st == dr ){
        Aint_Path[k][nod] = V[ Path[k][st] ];
    }else{

        int mid = ( st + dr ) >> 1;
        build( k, Nst, st, mid + 0 );
        build( k, Ndr, mid + 1, dr );

        Aint_Path[k][nod] = max( Aint_Path[k][Nst], Aint_Path[k][Ndr] );

    }

}

void update( int k, int nod, int st, int dr, int p ){

    int Nst = (nod<<1);
    int Ndr = ((nod<<1)|1);

    if( st == dr ){
        Aint_Path[k][nod] = V[ Path[k][st] ];
    }else{

        int mid = ( st + dr ) >> 1;
        if( p <= mid )
            update( k, Nst, st, mid + 0, p );
        else
            update( k, Ndr, mid + 1, dr, p );

        Aint_Path[k][nod] = max( Aint_Path[k][Nst], Aint_Path[k][Ndr] );

    }

}

int query( int k, int nod, int st, int dr, int a, int b ){

    int Nst = (nod<<1);
    int Ndr = ((nod<<1)|1);
    int Sol = 0;

    if( a <= st && dr <= b ){
        Sol = Aint_Path[k][nod];
    }else{

        int mid = ( st + dr ) >> 1;

        if( a <= mid )
            Sol = max( Sol, query( k, Nst, st, mid + 0, a, b ) );
        if( b > mid )
            Sol = max( Sol, query( k, Ndr, mid + 1, dr, a, b ) );

    }

    return Sol;

}

int get_ans( int x, int y ){

    int Ans = 0;
    while( Wh_Path[x] != Wh_Path[y] ){

        if( Lvl[ Father_Path[ Wh_Path[x] ] ] > Lvl[ Father_Path[ Wh_Path[y] ] ] ){

            Ans = max( Ans, query( Wh_Path[x], 1, 0, Path[ Wh_Path[x] ].size() - 1, 0, Pos[x] ) );
            x = Father_Path[ Wh_Path[x] ];

        }else{

            Ans = max( Ans, query( Wh_Path[y], 1, 0, Path[ Wh_Path[y] ].size() - 1, 0, Pos[y] ) );
            y = Father_Path[ Wh_Path[y] ];

        }

    }

    if( Pos[x] > Pos[y] )
        swap( x, y );

    Ans = max( Ans, query( Wh_Path[x], 1, 0, Path[ Wh_Path[x] ].size() - 1, Pos[x], Pos[y] ) );

    return Ans;

}

int main(){

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

    for( int i = 1; i < N; i++ ){

        int x, y; fin >> x >> y;
        edge[x].push_back( y );
        edge[y].push_back( x );

    }

    Lvl[1] = 1;
    dfs( 1, 0 );

    for( int i = 1; i <= Ind; i++ ){
        reverse( Path[i].begin(), Path[i].end() );
        for( int j = 0; j < Path[i].size(); j++ )
            Pos[ Path[i][j] ] = j;

        Aint_Path[i].resize( Path[i].size() * 4 + 5, 0 );
        build( i, 1, 0, Path[i].size() - 1 );
    }

    while( M-- ){

        int op, x, y; fin >> op >> x >> y;

        if( op == 0 ){

            V[x] = y;
            update( Wh_Path[x], 1, 0, Path[ Wh_Path[x] ].size() - 1, Pos[x] );

        }else
            fout << get_ans( x, y ) << "\n";

    }

    return 0;
}