Cod sursa(job #1100091)

Utilizator teoionescuIonescu Teodor teoionescu Data 6 februarie 2014 16:35:24
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.73 kb
#include<fstream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
#include<queue>
#define abs(x) ((x>0)?(x):(-(x)))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define ll long long
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int Nmax = 100005;
int lg[2*Nmax+2];
struct AI{
    int Size;
    vector<int> A;
    AI(int size){
        Size=size;
        A.insert (A.begin(),lg[size]*size+size,0);
    }
    void Update(int i,int st,int dr,int& w,int& val){
        if(st>=dr) A[i]=val;
        else{
            int mij=(st+dr)/2;
            if(w<=mij) Update(2*i,st,mij,w,val);
            if(w>mij) Update(2*i+1,mij+1,dr,w,val);
            A[i]=max(A[2*i],A[2*i+1]);
        }
    }
    int Query(int i,int st,int dr,int a,int b){
        if(a<=st && dr<=b) return A[i];
        int mij=(st+dr)/2;
        if(b<=mij) return Query(2*i,st,mij,a,b);
        if(a>mij) return Query(2*i+1,mij+1,dr,a,b);
        return max( Query(2*i,st,mij,a,mij) , Query(2*i+1,mij+1,dr,mij+1,b) );
    }
    void update(int wh,int val){
        Update(1,1,Size,wh,val);
    }
    int query(int a,int b){
        if(a>b) swap(a,b);
        return Query(1,1,Size,a,b);
    }
}; AI NewAI(int size){ return AI(size); }
vector<int> G[Nmax];
struct Query{
    int t,x,y,lca;
} Q[Nmax];
int v[Nmax],Wchain[Nmax],Wpos[Nmax],Heavy[Nmax],T[Nmax],Sons[Nmax],Choice[Nmax],NumChains;
vector<int> LineChain[Nmax];
queue<int> q;
vector<AI> Chain;
int E[2*Nmax],First[Nmax],Level[Nmax],mark[Nmax];
int N,M;
void Dfs(int x,int l){
    mark[x]=1;
    Level[x]=l;
    E[++E[0]]=x;
    First[x]=E[0];
    for(vector<int>::iterator it=G[x].begin();it!=G[x].end();++it){
        if(!mark[*it]){
            T[*it]=x,Sons[x]++;
            Dfs(*it,l+1);
            E[++E[0]]=x;
            Heavy[x]+=Heavy[*it];
        }
    }
    Heavy[x]++;
}
int MinL(int a,int b){
    if( Level[a] < Level[b] ) return a;
    return b;
}
vector<int> rmq[20];
void BuildRMQ(){
    Dfs(1,1);
    rmq[0].insert(rmq[0].begin(),E[0]+30,0);
    for(int i=1;i<=E[0];i++){
        rmq[0][i]=E[i];
    }
    for(int i=1;i<=lg[E[0]];i++){
        rmq[i].insert(rmq[i].begin(),E[0]-(1<<i)+30,0);
        for(int j=1;j<=E[0]-(1<<i)+1;j++){
            rmq[i][j]=MinL( rmq[i-1][j] , rmq[i-1][j+(1<<(i-1))] );
        }
    }
    for(int i=1;i<=M;i++){
        if(Q[i].t==1){
            int a=Q[i].x;
            int b=Q[i].y;
            a=First[a];
            b=First[b];
            if(a>b) swap(a,b);
            int dist=b-a;
            int log=lg[dist];
            int logs=(1<<log);
            Q[i].lca = MinL(rmq[log][a],rmq[log][a+dist-logs+1]);
        }
    }
    for(int i=0;i<=lg[E[0]];i++){
        rmq[i].clear();
    }
}
void ChainUpdate(int x){
    Chain[ Wchain[x] ].update( Wpos[x] , v[x] );
}
void BuildChains(){
    for(int i=1;i<=N;i++){
        if(!Sons[i]){
            q.push(i);
            Wchain[i]=++NumChains;
            LineChain[NumChains].push_back(i);
        }
    }
    while(!q.empty()){
        int x=q.front(); q.pop();
        if(!Wchain[x]){
            Wchain[x]=Wchain[ Choice[x] ];
            LineChain[ Wchain[x] ].push_back(x);
        }
        if(!Choice[ T[x] ] || Heavy[x] > Heavy[ Choice[ T[x] ] ]) Choice[ T[x] ]=x;
        Sons[T[x]]--;
        if(!Sons[T[x]]) q.push(T[x]);
    }
    Chain.push_back(NewAI(0));
    for(int i=1;i<=NumChains;i++){
        reverse( LineChain[i].begin() , LineChain[i].end() );
        LineChain[i].insert(LineChain[i].begin(),0);
        Chain.push_back(NewAI(LineChain[i].size()));
        for(unsigned int j=1;j<LineChain[i].size();j++){
            Wpos[ LineChain[i][j] ]=j;
            ChainUpdate(LineChain[i][j]);
        }
    }
}
int QueryPath(int a,int b){
    int m=0;
    while( Wchain[a] != Wchain[b] ){
        m=max( m , Chain[ Wchain[b] ].query(1,Wpos[b]) );
        b=T[ LineChain[Wchain[b]][1] ];
    }
    m=max( m , Chain[ Wchain[a] ].query(Wpos[a],Wpos[b]) );
    return m;
}
int main(){
    for(int i=2;i<=2*Nmax;i++) lg[i]=lg[i>>1]+1;
    in>>N>>M;
    for(int i=1;i<=N;i++) in>>v[i];
    for(int i=1;i<N;i++){
        int x,y;
        in>>x>>y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for(int i=1;i<=M;i++){
        in>>Q[i].t>>Q[i].x>>Q[i].y;
    }
    BuildRMQ();
    BuildChains();
    for(int i=1;i<=M;i++){
        int t,x,y,lca;
        t=Q[i].t;
        x=Q[i].x;
        y=Q[i].y;
        lca=Q[i].lca;
        if(t==0){
            v[x]=y;
            ChainUpdate(x);
        }
        if(t==1){
            out<< max( QueryPath(lca,x) , QueryPath(lca,y) )<<'\n';
        }
    }
    return 0;
}