Cod sursa(job #1263098)

Utilizator xtreme77Patrick Sava xtreme77 Data 13 noiembrie 2014 22:11:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.11 kb
/*
 * Code by Spiromanul
 */

#include <fstream>
#include <vector>
#include <algorithm>

#define pb push_back

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

using namespace std;

ifstream fin ( IN ) ;
ofstream fout ( OUT ) ;

int val [ MAX ] , level [ MAX ] , subarbore [ MAX ] , tata [ MAX ] ;

int lant [ MAX ] , drum , indexlant [ MAX ] ;

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

//////////////////////////////////////////////////// depth-first search begin

inline void dfs ( int nod , int lvl , int boss )
{
    level [ nod ] = lvl ;
    subarbore [ nod ] = 1 ;
    for ( auto x : gr [ nod ] )
        if ( x != boss )
        {
            tata [ x ] = nod ;
            dfs ( x , lvl + 1 , nod ) ;
            subarbore [ nod ] += subarbore [ x ] ;
        }
    if ( gr [ nod ].size ( ) == 1 and nod != 1 )
    {
        ++ drum ;
        lant [ nod ] = drum ;
        L [ drum ].pb ( 0 ) ;
        L [ drum ].pb ( nod ) ;
        indexlant [ nod ] = 1 ;
        return ;
    }
    int ce_trebuie = 0 ;
    for ( auto x : gr [ nod ] )
        if ( x != boss and subarbore [ x ] > subarbore [ ce_trebuie ] )
            ce_trebuie = x ;
    lant [ nod ] = lant [ ce_trebuie ] ;
    L [ lant [ nod ] ].pb ( nod ) ;
    indexlant [ nod ] = L [ lant [ nod ] ].size ( ) - 1 ;

}

//////////////////////////////////////////////////// depth-first search end


/////////////////////////////////////////////////// building begin

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

/////////////////////////////////////////////////// building end

////////////////////////////////////////////////// update poz begin
int update_poz , val_de_updatat ;
inline void update ( int nod , int st , int dr , int indice )
{
    if ( st == dr )
    {
        AINT [ indice ] [ nod ] = val_de_updatat ;
        return ;
    }
    int mij = ( st + dr ) >> 1 ;
    if ( update_poz <= mij )
        update ( nod << 1 , st , mij , indice ) ;
    else update ( nod << 1 | 1 , mij + 1 , dr , indice ) ;
    AINT [ indice ] [ nod ] = max ( AINT [ indice ] [ nod << 1 ] , AINT [ indice ] [ nod << 1 | 1 ] ) ;
}
////////////////////////////////////////////////// update poz end

////////////////////////////////////////////////// query begin

int a , b ;
inline void query ( int nod , int st , int dr , int indice , int &ans )
{
    if ( a <= st and dr <= b )
    {
        ans = max ( ans , AINT [ indice ] [ nod ] ) ;
        return ;
    }
    int mij = ( st + dr ) >> 1 ;
    if ( a <= mij )
        query ( nod << 1 , st , mij , indice , ans ) ;
    if ( b > mij )
        query ( nod << 1 | 1 , mij + 1 , dr , indice , ans ) ;

}

////////////////////////////////////////////////// query end

////////////////////////////////////////////////// gasesc maximul begin

inline int do_the_job ( int x , int y )
{
    int ans = 0 ;
    while ( 14 )
    {
        if ( lant [ x ] == lant [ y ] )
        {
            a = min ( indexlant [ x ] , indexlant [ y ] ) ;
            b = max ( indexlant [ x ] , indexlant [ y ] ) ;
            query ( 1 , 1 , ( int ) L [ lant [ x ] ].size ( ) - 1 , lant [ x ] , ans ) ;
            break ;
        }
        int x1 = L [ lant [ x ] ] [ 1 ] ;
        int y1 = L [ lant [ y ] ] [ 1 ] ;
        if ( level [ x1 ] < level [ y1 ] )
            swap ( x , y ) ;
        a = 1 ;
        b = indexlant [ x ] ;
        query ( 1 , 1 , ( int ) L [ lant [ x ] ].size ( ) - 1 , lant [ x ] , ans ) ;
        x = tata [ L [ lant [ x ] ] [ 1 ] ] ;
    }
    return ans ;
}

////////////////////////////////////////////////// gasesc maximul end

int main (               )
{
    int n , m ;
    fin >> n >> m ;
    for ( int i = 1 ; i <= n ; ++ i )
        fin >> val [ i ] ;
    for ( int i = 1 ; i < n ; ++ i )
    {
        int x , y ;
        fin >> x >> y ;
        gr [ x ].pb ( y ) ;
        gr [ y ].pb ( x ) ;
    }
    dfs ( 1 , 1 , 0 ) ;
    for ( int i = 1 ; i <= drum ; ++ i )
    {
        reverse ( L [ i ].begin ( ) + 1 , L [ i ].end ( ) ) ;
        AINT [ i ].resize ( 4 * ( L [ i ].size ( ) + 1 ) ) ;
        building ( 1 , 1 , ( int ) L [ i ].size ( ) - 1 , i ) ;
    }
    for ( int i = 1 ; i <= n ; ++ i )
        indexlant [ i ] = L [ lant [ i ] ].size ( ) - indexlant [ i ] ;
    for ( ; m ; -- m )
    {
        int tip , x , y ;
        fin >> tip >> x >> y ;
        if ( tip == 0 )
        {
            update_poz = indexlant [ x ] ; val_de_updatat = y ;
            update ( 1 , 1 , L [ lant [ x ] ].size ( ) - 1 , lant [ x ] ) ;
        }
        else {
            fout << do_the_job ( x , y ) << '\n' ;
        }
    }
    return 0;
}