Cod sursa(job #672343)

Utilizator tamas_iuliaTamas Iulia tamas_iulia Data 1 februarie 2012 21:41:28
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.73 kb
#include <stdio.h>
#include <vector>
#define pb push_back
#define Nmax 100005
using namespace std;

int N,M,rez_query,Nr_lanturi;
vector< int > Arbint[Nmax];
vector< int > v[Nmax],Lant[Nmax];
int Val[Nmax],use[Nmax],Niv[Nmax],Weight[Nmax];
int In_ce_lant[Nmax],Poz_in_lant[Nmax],Before_lant[Nmax],Start_lant[Nmax];

void Read(){
    int i,x,y;

    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    scanf("%d%d",&N,&M);
    for(i=1;i<=N;++i) scanf("%d",&Val[i]);
    for(i=1;i<N;++i){
        scanf("%d%d",&x,&y);
        v[x].pb(y);
        v[y].pb(x);
    }
}

void Df(int x){
    vector< int >:: iterator it;
    use[x]=1;

    if( v[x].size() == 1 && x!=1 )
    {
        Nr_lanturi ++;
        In_ce_lant[x]=Nr_lanturi;
        Lant[Nr_lanturi].pb(x);
        Poz_in_lant[x]=1;
        Start_lant[In_ce_lant[x]]=x;
        Weight[x]=1;
        return;
    }

    int wmax=0, fiu_wmax=0;
    for(it=v[x].begin(); it!=v[x].end(); ++it)
        if( ! use[ *it ] )
        {
            Niv[ *it ] = Niv[x] + 1;

            Df(*it);

            Weight[x] += Weight[*it];
            if( Weight[*it] > wmax )
            {
                wmax = Weight[*it];
                fiu_wmax = *it;
            }
        }

    In_ce_lant[x]=In_ce_lant[fiu_wmax];
    Poz_in_lant[x] = Poz_in_lant[Lant[In_ce_lant[x]].back()]+1;
    Lant[In_ce_lant[x]].pb(x);
    Start_lant[In_ce_lant[x]]=x;

    for(it=v[x].begin(); it!=v[x].end(); ++it)
        if( Niv[*it] > Niv[x] && *it != fiu_wmax )
        {
            Before_lant[In_ce_lant[*it]] = x;
            Start_lant[In_ce_lant[*it]]=*it;
        }
}

inline void Update(int care_arb, int nod, int l,int r, int poz,int val){
    if( l == r ){
        Arbint[care_arb][nod] = val;
        return;
    }

    int m=l+(r-l)/2;
    if( poz<=m ) Update(care_arb, 2*nod, l, m, poz, val);
    else Update(care_arb, 2*nod+1, m+1, r, poz, val);

    Arbint[care_arb][nod] = max( Arbint[care_arb][2*nod], Arbint[care_arb][2*nod+1] );
}

inline void Query(int care_arb, int nod, int l, int r, int x, int y){
    if( x<=l && r<= y ){
        rez_query = max( rez_query, Arbint[care_arb][nod] );
        return;
    }

    int m=l+(r-l)/2;
    if( x<=m ) Query( care_arb, 2*nod, l, m, x, y);
    if( m<y ) Query( care_arb, 2*nod+1, m+1, r, x, y);
}

void Make_arbint(){
    vector< int >:: iterator it;
    int i;

    for(i=1;i<=Nr_lanturi;++i){

        Arbint[i].reserve( Lant[i].size() * 4 );

        for(it=Lant[i].begin(); it!=Lant[i].end(); ++it)
            Update( i, 1, 1, Lant[i].size(), Poz_in_lant[*it], Val[*it]);
    }
}

inline void Solve(){
    int i,tip,x,y;

    for(i=1;i<=M;++i){

        scanf("%d%d%d",&tip,&x,&y);

        if( tip == 0 ){
            Update( In_ce_lant[x], 1, 1, Lant[In_ce_lant[x]].size(), Poz_in_lant[x], y );
        }
        else{
            rez_query = 0;

            while( 1 ){

                if( In_ce_lant[x] == In_ce_lant[y] ){

                    if( Poz_in_lant[x] > Poz_in_lant[y] ) swap(x,y);

                    Query( In_ce_lant[x], 1, 1, Lant[In_ce_lant[x]].size(), Poz_in_lant[x],Poz_in_lant[y]);

                    break;
                }

                if( Niv[Before_lant[In_ce_lant[x]]] < Niv[Before_lant[In_ce_lant[y]]])
                    swap(x,y);

                Query( In_ce_lant[x], 1, 1, Lant[In_ce_lant[x]].size(), Poz_in_lant[x], Lant[In_ce_lant[x]].size()  );
                x = Before_lant[In_ce_lant[x]];
            }

            printf("%d\n", rez_query);
        }
    }
}

int main(){

    Read();
    Niv[1]=1, Df(1);
    Make_arbint();
    Solve();

    fclose(stdin); fclose(stdout);
    return 0;
}