Cod sursa(job #1967138)

Utilizator DysKodeTurturica Razvan DysKode Data 15 aprilie 2017 22:27:28
Problema Heavy Path Decomposition Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 4.26 kb
#include <bits/stdc++.h>

using namespace std;

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

#define f first
#define s second

int W[100010],use[100010],father[100010],tag[100010],pos[100010],i,j,n,nivel[100010],first[100010],x,y,m,nrLanturi,r,v[100010],t;
int a[100010],b[100010],k,ANS;
vector< pair<int,int> > G[100010];
vector< int > lant[100010];

struct SegTree
{
    int n,*v,ans;
    SegTree( int siz )
    {
        n = siz;
        v = new int[ 4 * n ];
        memset( v , 0 , sizeof( v ) );
    }
    void UPD( int nod, int left, int right, int poz, int val )
    {
        int middle = ( left + right ) / 2;
        if( left == right )
        {
            v[ nod ] = val;
            return;
        }
        if( poz <= middle )
            UPD( 2 * nod , left , middle , poz , val );
        else
            UPD( 2 * nod + 1 , middle + 1 , right , poz , val );
        v[ nod ] = max( v[ 2 * nod ] , v[ 2 * nod + 1 ] );
    }
    void Update( int poz, int val )
    {
        UPD( 1 , 1 , n , poz , val );
    }
    int QR( int nod, int left, int right, int L, int R )
    {
        int middle = ( left + right ) / 2;
        if( left > R || right < L )
            return 0;
        if( L <= left && right <= R )
            return v[ nod ];
        return max( QR( 2 * nod , left , middle , L , R ) ,
                    QR( 2 * nod + 1 , middle + 1 , right , L , R ) );
    }
    int Query( int L, int R )
    {
        return QR( 1 , 1 , n , L , R );
    }
}*arb[ 100010 ];

void DF1( int nod , int ftr )
{
    use[ nod ] = 1;
    W[ nod ] = 1;
    father[ nod ] = ftr;
    nivel[ nod ] = nivel[ ftr ] + 1;
    for( int i = 0 ; i < G[ nod ].size() ; i++ )
    {
        if( !use[ G[ nod ][ i ].s ] )
        {
            DF1( G[ nod ][ i ].s , nod );
            W[ nod ] += W[ G[ nod ][ i ].s ];
            G[ nod ][ i ].f = W[ G[ nod ][ i ].s ];
        }
    }
    sort( G[ nod ].begin() , G[ nod ].end() );
}

void DF2( int nod )
{
    lant[ nrLanturi ].push_back( nod );
    tag[ nod ] = nrLanturi;
    pos[ nod ] = lant[ nrLanturi ].size() - 1;
    first[ nrLanturi ] = lant[ nrLanturi ][ 1 ];
    if( G[ nod ].size() == 1 && nod != 1 )
    {
        arb[ nrLanturi ] = new SegTree( pos[ nod ] );
        for( auto it : lant[ nrLanturi ] )
            (*arb[ nrLanturi ]).Update( pos[ it ] , v[ it ] );
        nrLanturi++;
        lant[ nrLanturi ].push_back( 0 );
    }
    for( int i = G[ nod ].size() - 1 ; i >= 0 ; i-- )
    {
        if( G[ nod ][ i ].s == father[ nod ] )
            continue;
        DF2( G[ nod ][ i ].s );
    }
}

void drum( int nod, int a[] )
{
    if( tag[ nod ] == 0 )
        return;
    drum( father[ first[ tag[ nod ] ] ] , a );
    a[ ++a[ 0 ] ] = nod;
}

void solve( int nod )
{
    if( nivel[ nod ] < nivel[ k ] )
        return;
    if( nivel[ first[ tag[ nod ] ] ] >= nivel[ k ] )
        ANS = max( ANS , (*arb[ tag[ nod ] ]).Query( 1 , pos[ nod ] ) );
    else if( nivel[ first[ tag[ nod ] ] ] < nivel[ k ] )
        ANS = max( ANS , (*arb[ tag[ nod ] ]).Query( pos[ k ] , pos[ nod ] ) );
    solve( father[ first[ tag[ nod ] ] ] );
}

int main()
{
    lant[ 1 ].push_back( 0 );
    nrLanturi = 1;
    fin>>n>>m;
    for( i = 1 ; i <= n ; i++ )
    {
        fin>>v[ i ];
    }
    for( i = 1 ; i < n ; i++ )
    {
        fin>>x>>y;
        G[ x ].push_back( {0,y});
        G[ y ].push_back( {0,x});
    }
    DF1( 1 , 0 );
    DF2( 1 );
    for( i = 1 ; i <= m ; i++ )
    {
        fin>>t>>x>>y;
        if( t == 0 )
        {
            (*arb[ tag[ x ] ]).Update( pos[ x ] , y );
        }
        else
        {
            a[ 0 ] = 0;
            drum( x , a );
            b[ 0 ] = 0;
            drum( y , b );
            for( j = 1 ; j <= min( a[ 0 ] , b[ 0 ] ) ; j++ )
            {
                if( j == min( a[ 0 ] , b[ 0 ] ) )
                    break;
                if( a[ j ] != b[ j ] )
                    break;
            }
            if( nivel[ a[ j ] ] < nivel[ b[ j ] ] )
                k = a[ j ];
            else
                k = b[ j ];
            ANS = 0;
            solve( x );
            solve( y );
            fout<<ANS<<'\n';
        }
    }
return 0;
}