Cod sursa(job #1715152)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 9 iunie 2016 23:32:00
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.66 kb
#include<fstream>
#include<vector>
#include<algorithm>

using namespace std;

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

typedef vector< int > graf;

const int nmax = 1e5;
int n;
bool viz[ nmax + 1 ];
int dp[ nmax + 1 ];
int v[ nmax + 1 ], ad[ nmax + 1 ];
int lant[ nmax + 1 ], ind[ nmax + 1 ];

graf g[ nmax + 1 ];

inline int max2( int a, int b ) {
    return ( a > b ? a : b );
}

class Lant{
public:
    int tata;
    vector< int > nodes;
    vector< int > aint;

    inline void init( int dim ) {
        aint.resize( 4 * dim + 1 );
    }
    inline void update( int nod, int x, int y, int pos, int val ) {
        if ( x == y ) {
            aint[ nod ] = val;
            return ;
        }
        int mij = (x + y) / 2;
        if ( pos <= mij ) {
            update( 2 * nod, x, mij, pos, val );
        } else {
            update( 2 * nod + 1, mij + 1, y, pos, val );
        }
        aint[ nod ] = max2( aint[ 2 * nod ], aint[ 2 * nod + 1 ] );
    }
    inline int query( int nod, int x, int y, int st, int dr ) {
        int ans = 0;
        if ( st <= x && y <= dr ) {
            return aint[ nod ];
        }
        int mij = (x + y) / 2;
        if ( st <= mij ) {
            ans = max2( ans, query( 2 * nod, x, mij, st, dr ) );
        }
        if ( dr >= mij + 1 ) {
            ans = max2( ans, query( 2 * nod + 1, mij + 1, y, st, dr ) );
        }
        return ans;
    }
} l[ nmax + 1 ];

void dfs( int nod, int tata = 0 ) {
    viz[ nod ] = 1;
    dp[ nod ] = 1;
    int fiug, sol = -1;
    for( auto it : g[ nod ] ) {
        if ( it != tata ) {
            ad[ it ] = ad[ nod ] + 1;
            dfs( it, nod );

            dp[ nod ] += dp[ it ];
            if ( dp[ it ] > sol ) {
                fiug = it;
                sol = dp[ it ];
            }
        }
    }

    if ( sol == -1 ) {
        l[ nod ].tata = 0;
        lant[ nod ] = nod;
    } else {
        lant[ nod ] = lant[ fiug ];
        for( auto it : g[ nod ] ) {
            if ( it != tata && it != fiug ) {
                l[ lant[ it ] ].tata = nod;
            }
        }
    }
    l[ lant[ nod ] ].nodes.push_back( nod );
}
void aranjeaza_lanturi() {
    for( int i = 1; i <= n; ++ i ) {
        reverse( l[ i ].nodes.begin(), l[ i ].nodes.end() );
        int dim = ( int )l[ i ].nodes.size();
        l[ i ].init( dim );

        for( vector< int >::iterator it = l[ i ].nodes.begin(); it != l[ i ].nodes.end(); ++ it ) {
            ind[ *it ] = it - l[ i ].nodes.begin() + 1;
            l[ i ].update( 1, 1, dim, ind[ *it ], v[ *it ] );
        }
    }
}
int solve( int x, int y ) {
    int ans = -1;
    while ( lant[ x ] != lant[ y ] ) {
        if ( ad[ l[ lant[ x ] ].tata ] > ad[ l[ lant[ y ] ].tata ] ) {
            swap( x, y );
        }
        ans = max2( ans, l[ lant[ y ] ].query( 1, 1, ( int )l[ lant[ y ] ].nodes.size(), 1, ind[ y ] ) );
        y = l[ lant[ y ] ].tata;
    }

    if ( ind[ x ] > ind[ y ] ) {
        swap( x, y );
    }
    ans = max2( ans, l[ lant[ x ] ].query( 1, 1, ( int )l[ lant[ x ] ].nodes.size(), ind[ x ], ind[ y ] ) );
    return ans;
}
int main() {
    int m;
    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;
        g[ x ].push_back( y );
        g[ y ].push_back( x );
    }

    ad[ 1 ] = 1;
    dfs( 1 );
    aranjeaza_lanturi();

    while ( m -- ) {
        int t, x, y;
        fin >> t >> x >> y;
        if ( t == 0 ) {
            l[ lant[ x ] ].update( 1, 1, ( int )l[ lant[ x ] ].nodes.size(), ind[ x ], y );
        } else {
            fout << solve( x, y ) << "\n";
        }
    }

    fin.close();
    fout.close();
    return 0;
}