Cod sursa(job #1100105)

Utilizator teoionescuIonescu Teodor teoionescu Data 6 februarie 2014 16:46:01
Problema Heavy Path Decomposition Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 5.24 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 size=300000;
char buff[size+5];
int pos=size+1;
inline bool rable(char& c){
    return ('0'<=c && c<='9');
}
int Read(int& x){
    x=0;
    while(!rable(buff[pos])){
        pos++;
        if(pos>=size) in.read(buff,size),pos=0;
    }
    while(rable(buff[pos])){
        x=x*10 + int(buff[pos]) - '0';
        pos++;
        if(pos>=size) in.read(buff,size),pos=0;
    }
}
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];
int v[Nmax],Wchain[Nmax],Wpos[Nmax],Heavy[Nmax],T[Nmax],Sons[Nmax],Choice[Nmax],TChain[Nmax],NumChains;
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]++;
}
struct LCA{
    int MinL(int a,int b){
        if( Level[a] < Level[b] ) return a;
        return b;
    }
    int A[20*Nmax];
    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]=MinL(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 MinL( 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,E[0],wh,val);
    }
    int query(int a,int b){
        a=First[a];
        b=First[b];
        if(a>b) swap(a,b);
        return Query(1,1,E[0],a,b);
    }
} Lca;
void ChainUpdate(int x){
    Chain[ Wchain[x] ].update( Wpos[x] , v[x] );
}
void BuildChains(){
    vector<int> LineChain[Nmax];
    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]);
            TChain[ LineChain[i][j] ]=T[ LineChain[i][1] ];
        }
        LineChain[i].clear();
    }
}
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=TChain[b];
    }
    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;
    Read(N);
    Read(M);
    for(int i=1;i<=N;i++) Read(v[i]);
    for(int i=1;i<N;i++){
        int x,y;
        Read(x);
        Read(y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    Dfs(1,1);
    for(int i=1;i<=E[0];i++) Lca.update(i,E[i]);
    BuildChains();
    for(int i=1;i<=M;i++){
        int t,x,y;
        Read(t);
        Read(x);
        Read(y);
        if(t==0){
            v[x]=y;
            ChainUpdate(x);
        }
        if(t==1){
            int lca=Lca.query(x,y);
            out<< max( QueryPath(lca,x) , QueryPath(lca,y) )<<'\n';
        }
    }
    return 0;
}