Cod sursa(job #1450156)

Utilizator xtreme77Patrick Sava xtreme77 Data 11 iunie 2015 18:08:07
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.75 kb
/**
 * Code by Patrick Sava
 * "Spiru Haret" National College of Bucharest
 **/

# include "fstream"
# include "cstring"
# include "vector"
# include "queue"
# include "bitset"
# include "algorithm"
# include "map"
# include "unordered_map"
# include "deque"
# include "string"
# include "iomanip"
# include "cmath"
# include "stack"
# include "cassert"

const char IN [ ] =  "heavypath.in" ;
const char OUT [ ] = "heavypath.out" ;
const int MAX = 100500 ;

# define pb push_back
# define mp make_pair
# define FORN( a , b , c ) for ( int a = b ; a <= c ; ++ a )
# define FORNBACK( a , b , c ) for ( int a = b ; a >= c ; -- a )

using namespace std ;

ifstream cin ( IN ) ;
ofstream cout ( OUT ) ;

vector < int > gr [ MAX ] ;
vector < int > lant [ MAX ] ;
vector < int > AINT [ MAX ] ;

int lantdenod [ MAX ] , val [ MAX ] , nivel [ MAX ] , tata [ MAX ] , nr_lant , sub [ MAX ] , poz [ MAX ] ;

inline void dfs ( int nod , int boss , int lvl )
{
    nivel [ nod ] = lvl ;
    sub [ nod ] = 1 ;
    for ( auto x : gr [ nod ] )
        if ( x != boss )
        {
            tata [ x ] = nod ;
            dfs ( x , nod , lvl + 1 ) ;
            sub [ nod ] += sub [ x ] ;
        }
    if ( gr [ nod ].size ( ) == 1 and nod != 1 )
    {
        ++ nr_lant ;
        lant [ nr_lant ].pb ( 0 ) ;
        lant [ nr_lant ].pb ( nod ) ;
        lantdenod [ nod ] = nr_lant ;
        poz [ nod ] = 1 ;
        return ;
    }

    int CET = 0 ;

    for ( auto x : gr [ nod ] )
    {
        if ( x != boss and sub [ x ] > sub [ CET ] )
            CET = x ;
    }
    lantdenod [ nod ] = lantdenod [ CET ] ;
    lant [ lantdenod [ nod ] ].pb ( nod ) ;
    poz [ nod ] = lant [ lantdenod [ nod ] ].size ( ) - 1 ;
}

inline void build ( int lantz , int nod , int st , int dr )
{
    if ( st == dr ){
        AINT [ lantz ] [ nod ] = val [ lant [ lantz ] [ st ] ] ;
        return ;
    }
    int mij = ( st + dr ) >> 1 ;
    build ( lantz , nod << 1 , st , mij ) ;
    build ( lantz , nod << 1 | 1 , mij + 1 , dr ) ;
    AINT [ lantz ] [ nod ] = max ( AINT [ lantz ] [ nod << 1 ], AINT [ lantz ] [ nod << 1 | 1 ] ) ;
}

inline void update ( int lantz , int nod , int st , int dr , int pos , int valuee )
{
    if ( st == dr )
    {
        AINT [ lantz ] [ nod ] = valuee ;
        return ;
    }
    int mij = ( st + dr ) >> 1 ;
    if ( pos <= mij )
        update ( lantz , nod << 1 , st , mij , pos , valuee ) ;
    else update ( lantz , nod << 1 | 1 , mij + 1 , dr , pos , valuee ) ;
    AINT [ lantz ] [ nod ] = max ( AINT [ lantz ] [ nod << 1 ], AINT [ lantz ] [ nod << 1 | 1 ] ) ;
}

inline int query ( int lantz , int nod , int st , int dr , int a , int b )
{
    if ( a <= st and dr <= b )
    {
        return AINT [ lantz ] [ nod ] ;
    }
    int mij = ( st + dr ) >> 1 ;
    int kk1 = - ( 1 << 30 ) , kk2 = - ( 1 << 30 ) ;
    if ( a <= mij )
        kk1 = query ( lantz , nod << 1 , st , mij , a , b ) ;
    if ( b > mij )
        kk2 = query ( lantz , nod << 1 | 1 , mij + 1 , dr , a , b ) ;
    return max ( kk1 , kk2 ) ;
}

int solve ( int x , int y )
{
    int CET = - 14 ;
    while ( 1 )
    {
        int xx = lantdenod [ x ] ;
        int yy = lantdenod [ y ] ;
        if ( xx == yy )
        {
            int a = min ( poz [ x ] , poz [ y ] ) ;
            int b = max ( poz [ x ] , poz [ y ] ) ;
            CET = max ( CET , query ( xx , 1 , 1 , lant [ xx ].size ( ) - 1 , a , b ) ) ;
            break ;
        }
        int bossa = lant [ xx ] [ 1 ] ;
        int bossb = lant [ yy ] [ 1 ] ;
        if ( nivel [ bossa ] < nivel [ bossb ] )
            swap ( x , y ) ;

        xx = lantdenod [ x ] ;
        yy = lantdenod [ y ] ;

        CET = max ( CET , query ( xx , 1 , 1 , lant [ xx ].size ( ) - 1 , 1 , poz [ x ] ) ) ;
        x = tata [ lant [ xx ] [ 1 ] ] ;
    }
    return CET ;
}

int main ( void )
{
    int n , m ;
    cin >> n >> m ;
    FORN ( i , 1 , n )
        cin >> val [ i ] ;
    FORN ( i , 2 , n )
    {
        int x , y ;
        cin >> x >> y ;
        gr [ x ].pb ( y ) ;
        gr [ y ].pb ( x ) ;
    }
    dfs ( 1 , 0 , 0 ) ;
    FORN ( i , 1 , nr_lant )
    {
        reverse ( lant [ i ].begin ( ) + 1 , lant [ i ].end ( ) ) ;
        AINT [ i ].resize ( 4 * lant [ i ].size ( ) ) ;
        build ( i , 1 , 1 , lant [ i ].size ( ) - 1 ) ;
    }
    FORN ( i , 1 , n )
        poz [ i ] = lant [ lantdenod [ i ] ].size ( ) - poz [ i ] ;
    while ( m -- )
    {
        int tip , x , y ;
        cin >> tip >> x >> y ;
        if ( tip == 0 )
        {
            update ( lantdenod [ x ] , 1 , 1 , lant [ lantdenod [ x ] ].size ( ) - 1 , poz [ x ] , y ) ;
        }
        else cout << solve ( x , y ) << '\n' ;
    }
    return 0;
}