Cod sursa(job #1415466)

Utilizator bogdanpaunFMI Paun Bogdan Gabriel bogdanpaun Data 4 aprilie 2015 17:52:20
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.44 kb
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;

#define N 100005
int n , m ;
int v[N] , niv[N] , use[N] , w[N] , nl , l[N] , ldim[N] , ltata[N] , lniv[N]  ;
int lpoz[N]  , aint[4*N] , sol      ;
vector<int> g[N],p[N];
int a,b,c;

//////
/////
////
///
//

void dfs(int nod){
    use[nod] = 1;
      w[nod] = 1;
    int hn = 100004 , fr = -1;

    for(vector<int> :: iterator it = g[nod].begin() ; it != g[nod].end() ; ++it){
        if( use[*it] ) continue;
        fr = 0;
        niv[*it] = niv[nod] + 1;

        dfs(*it);

        w[nod] += w[*it];
        if( w[ hn ] < w[*it] )
            hn = *it;
    }

    if( fr ){
        l[nod] = ++nl;
        ldim[ nl ] = 1;
        p[nl].push_back(nod);
        return ;
    }

    l[nod] = l[hn];
    ++ldim[ l[nod] ];
    p[l[nod]].push_back(nod);

    for(vector<int> :: iterator it = g[nod].begin() ; it != g[nod].end() ; ++it){
        if( *it == hn || niv[*it] < niv[nod] ) continue;
        ltata[ l[*it] ] = nod;
        lniv[ l[*it] ]  = niv[nod];

    }
}

void build(int x,int l , int r , int dec,int lant){
    if( l == r ){
        aint[ x + dec ] = v[p[lant][l -1]];
        return ;
    }
    int m = (l+r)>>1;
    build( x*2  , l   ,   m  ,  dec  , lant );
    build( x*2+1, m+1 ,   r  ,  dec  , lant );
    aint[dec + x] = max( aint[ dec + x*2 ] , aint[dec + x*2+1] );
}

void update(int x,int l,int r,int poz,int val,int dec){
    if(  l == r ){
        aint[ x + dec ] = val;
        return ;
    }
    int m = (l+r)>>1;
    if( poz <= m )
        update( x*2 , l   ,   m   ,  poz , val , dec );
    else
        update( x*2+1 , m+1 ,   r   ,  poz , val , dec );
    aint[dec + x] = max( aint[ dec + x*2 ] , aint[dec + x*2+1] );

}

int query(int x,int l,int r,int ql , int qr,int dec){
    if( ql <= l && r <= qr )
        return aint[dec + x];
    int m = (l+r)>>1;
    int rez = -1 ;
    if( ql <= m )
        rez = max( rez , query(x*2  , l   ,   m   ,  ql , qr , dec) );
    if(   m < qr)
        rez = max( rez , query(x*2+1, m+1 ,   r   ,  ql , qr , dec) );
    return rez;

}

int main()
{
    freopen("heavypath.in" , "r" , stdin);
    freopen("heavypath.out", "w" , stdout);

    scanf("%d %d",&n,&m);

    for(int i =1; i<=n;++i){
        scanf("%d",&v[i]);
    }


    for(int i=1; i< n;++i){
        scanf("%d %d",&a,&b);
        g[a] . push_back(b);
        g[b] . push_back(a);
    }

    niv[1] = 1;
    w[100004] = -1;
    dfs(1);

    for(int i=1;i <= nl; ++i){
        reverse( p[i].begin() , p[i].end() );
        lpoz[i] = lpoz[i-1] + ldim[i-1]*4;
        build( 1 , 1 , ldim[i] , lpoz[i] , i );
    }

     for(int i=1;i<=m;++i){
        scanf("%d %d %d",&c,&a,&b);
        if( c == 0 ){
            update( 1 , 1 , ldim[l[a]] , niv[a] - lniv[ l[a] ] , b , lpoz[l[a]] );
        }else{
            sol = 0;
            while( true ){
                if( l[a] == l[b] ){
                    if( niv[a] > niv[b] ) swap(a,b);
                    sol = max( sol , query(1 , 1 , ldim[l[a]] , niv[a] - lniv[l[a]], niv[b] - lniv[l[a]], lpoz[l[a]] ) );
                    break;
                }
                if( lniv[l[a]] < lniv[l[b]] ) swap(a,b);
                sol = max(sol , query(1 , 1 , ldim[l[a]] , 1 , niv[a] - lniv[l[a]] , lpoz[l[a]] ));
                a = ltata[l[a]];
            }
            printf("%d\n",sol);

        }
    }





    return 0;
}