Cod sursa(job #1169469)

Utilizator teoionescuIonescu Teodor teoionescu Data 11 aprilie 2014 13:51:52
Problema Heavy Path Decomposition Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 5.09 kb
#include<fstream>
#include<algorithm>
#include<cstring>
#include<vector>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int size=1<<12;
char buff[size+1];
int pos=size+1;
inline bool rable(char& c){return ('0'<=c && c<='9');}
void Read(int& x){
    x=0;
    if(pos>=size) in.read(buff,size),pos=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 = 100002;
int mark[Nmax],H[Nmax],L[Nmax],First[Nmax];
vector<int> E;
vector<int> G[Nmax];
int v[Nmax];
vector<int> Chains[Nmax];
int ChainFather[Nmax],NumChains,PartOfChain[Nmax],Catelea[Nmax];

int DfsH(int x,int lev){
    mark[x]=1;
    L[x]=lev;
    for(vector<int>::iterator it=G[x].begin();it!=G[x].end();++it){
        if(!mark[*it]) H[x]+=DfsH(*it,lev+1);
    }
    return H[x]+1;
}

void DfsChain(int x,int wh){
    mark[x]=1;
    Chains[wh].push_back(x);
    PartOfChain[x]=wh;
    Catelea[x]=Chains[wh].size();
    int maxh=-1,maxw;
    for(vector<int>::iterator it=G[x].begin();it!=G[x].end();++it){
        if(!mark[*it]){
            if(H[*it]>maxh) maxh=H[*it],maxw=*it;
        }
    }
    for(vector<int>::iterator it=G[x].begin();it!=G[x].end();++it){
        if(!mark[*it]){
            if(*it==maxw) DfsChain(*it,wh);
            else{
                ChainFather[++NumChains]=x;
                DfsChain(*it,NumChains);
            }
        }
    }
}

void DfsE(int x){
    mark[x]=1;
    E.push_back(x);
    First[x]=E.size();
    for(vector<int>::iterator it=G[x].begin();it!=G[x].end();++it){
        if(!mark[*it]){
            DfsE(*it);
            E.push_back(x);
        }
    }
}

struct Aint{
    int log(int x){
        int l=0;
        for(int e=0;(1<<e)<=x;e++) l++;
        return l;
    }
    vector<int> A;
    int Size,rule;
    void Update(int i,int st,int dr,int wh,int val){
        if(st>=dr) A[i]=val;
        else{
            int mij=(st+dr)/2;
            if(wh<=mij) Update(2*i,st,mij,wh,val);
            else Update(2*i+1,mij+1,dr,wh,val);
            if(rule==0) A[i]=max(A[2*i],A[2*i+1]);
            if(rule==1){
                if(L[A[2*i]]<L[A[2*i+1]]) A[i]=A[2*i];
                else A[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];
        else{
            int mij=(st+dr)/2;
            if(b<=mij) return Query(2*i,st,mij,a,b);
            else if(a>mij) return Query(2*i+1,mij+1,dr,a,b);
            else{
                int aa=Query(2*i,st,mij,a,mij);
                int bb=Query(2*i+1,mij+1,dr,mij+1,b);
                if(rule==0) return max(aa,bb);
                if(rule==1){
                    if(L[aa]<L[bb]) return aa;
                    else return bb;
                }
            }
        }
    }
    void update(int wh,int val){
        Update(1,1,Size,wh,val);
    }
    int query(int a,int b){
        return Query(1,1,Size,a,b);
    }
    Aint(){}
    Aint(vector<int> V,int _r){
        rule=_r;
        Size=V.size();
        A=vector<int>(5*(Size+1));
        if(rule==0) for(int i=0;i<V.size();i++) update(i+1,v[V[i]]);
        if(rule==1) for(int i=0;i<V.size();i++) update(i+1,V[i]);
    }
    void print(int i,int st,int dr){
        int minn=E[st-1];
        for(int j=st;j<=dr;j++) if(L[E[j-1]]<minn) minn=E[j-1];
        out<<st<<' '<<dr<<' '<<A[i]<<' '<<minn<<'\n';
        if(st>=dr) return;
        int mij=(st+dr)/2;
        print(2*i,st,mij);
        print(2*i+1,mij+1,dr);
    }
};
vector<Aint> Aints;
Aint rmq;

int lca(int x,int y){
    x=First[x];
    y=First[y];
    if(x>y) swap(x,y);
    return rmq.query(x,y);
}

int ChainQuery(int x,int y){
    int Max=0;
    int cx=PartOfChain[x];
    int cy=PartOfChain[y];
    while(cx!=cy){
        Max=max(Max,Aints[cx-1].query(1,Catelea[x]));
        x=ChainFather[cx];
        cx=PartOfChain[x];
    }
    Max=max(Max,Aints[cx-1].query(Catelea[y],Catelea[x]));
    return Max;
}

int N,M;
int main(){
    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);
    }
    int root=1;
    memset(mark,0,sizeof(mark)); DfsH(root,1);
    memset(mark,0,sizeof(mark)); DfsChain(root,++NumChains);
    memset(mark,0,sizeof(mark)); DfsE(root);
    for(int i=1;i<=NumChains;i++){
        Aints.push_back( Aint(Chains[i],0) );
    }
    rmq=Aint(E,1);
    for(int i=1;i<=M;i++){
        int t,x,y;
        Read(t);
        Read(x);
        Read(y);
        if(t==0){
            v[x]=y;
            Aints[PartOfChain[x]-1].update(Catelea[x],y);
        }
        if(t==1){
            int l=lca(x,y);
            out<<max( ChainQuery(x,l) , ChainQuery(y,l) )<<'\n';
        }
    }
    return 0;
}