Cod sursa(job #1310928)

Utilizator Adrian1997Radulescu Adrian Adrian1997 Data 7 ianuarie 2015 14:59:05
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 4.7 kb
#include <fstream>
#include <vector>
#include <bitset>
#define DIM 100011
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int n,m,k,z;
int p[DIM]; //puterile lui 2 asociate fiecarei pozitie
int F[DIM]; //prima aparitie a unui nod in parcurgerea Euler
int poz[DIM]; //lantul din care face parte un nod
int nr[1011]; //cate noduri are fiecare lant
int nr1[DIM];//cate noduri are fiecare fiu in subarborele sau
int loc[DIM]; //pozitia unui nod in lantul din care face parte
int T[DIM]; //tatal unui nod
int a[20][2*DIM]; //matricea RMQ
long long V[DIM]; //valuarea unui nod
pair<int,int> E[2*DIM]; //vectorul corespunzator parcurgerii euler <nod,nivel>

vector<int> L[DIM];//liste de vecini
vector<int> LT[50011];//liste de lanturi
vector<int> A[50011];//arborii de intervale asociati lanturilor
bitset<DIM> viz;

void dfs(int nod,int niv,int tata){
    vector<int>::iterator it;
    int maxim=0,pz;
    viz[nod]=1;
    nr1[nod]=1;
    T[nod]=tata;
    E[++k]=make_pair(nod,niv);
    if(!F[nod]) F[nod]=k;
    if(L[nod].size()==1 && nod!=1){
        LT[++z].push_back(0);
        LT[z].push_back(nod);
        poz[nod]=z;
        nr[z]=1;
        return;
    }
    for(it=L[nod].begin();it!=L[nod].end();it++){
        if(viz[*it]) continue;
        dfs(*it,niv+1,nod);
        nr1[nod]+=nr1[*it];
        E[++k]=make_pair(nod,niv);
        if(nr1[*it]>maxim)
            maxim=nr1[*it],pz=poz[*it];
    }
    nr[pz]++;
    LT[pz].push_back(nod);
    poz[nod]=pz;
}

void build(int i,int nod,int p,int u){
    if(p==u){
        A[i][nod]=LT[i][p];
        return;
    }
    int mid=p+(u-p)/2;
    build(i,2*nod,p,mid);
    build(i,2*nod+1,mid+1,u);
    //A[i][nod]=max(A[i][2*nod],A[i][2*nod+1]);
    if(V[A[i][2*nod]]>V[A[i][2*nod+1]])
        A[i][nod]=A[i][2*nod];
    else
        A[i][nod]=A[i][2*nod+1];
}

void update(int i,int nod,int p,int u,int a,int b){
    if(p==u)
        return;
    int mid=p+(u-p)/2;
    if(a<=mid)
        update(i,2*nod,p,mid,a,b);
    else
        update(i,2*nod+1,mid+1,u,a,b);
    if(V[A[i][2*nod]]>V[A[i][2*nod+1]])
        A[i][nod]=A[i][2*nod];
    else
        A[i][nod]=A[i][2*nod+1];
}

int query(int i,int nod,int p,int u,int a,int b){
    if(a<=p && u<=b){
        return A[i][nod];
    }
    int mid=p+(u-p)/2,st=0,dr=0;
    if(a<=mid)
        st=query(i,2*nod,p,mid,a,b);
    if(b>mid)
        dr=query(i,2*nod+1,mid+1,u,a,b);
    if(V[st]>V[dr])
        return st;
    else
        return dr;
}

int main(void){
    register int q,q1,q2,i,j,x,y,jv,b,t,x1,y1,LCA;

    f>>n>>m;
    for(i=1;i<=n;i++) f>>V[i];
    for(i=1;i<n;i++){
        f>>x>>y;
        L[x].push_back(y);
        L[y].push_back(x);
    }
    dfs(1,1,0);
    //sortam lanturile
    for(t=1;t<=z;t++){
        for(i=1,j=nr[t];i<=j;i++,j--)
            swap(LT[t][i],LT[t][j]),loc[LT[t][i]]=i,loc[LT[t][j]]=j;
    }

    a[0][1]=1;
    for(i=2;i<=k;i++) p[i]=1+p[i/2],a[0][i]=i;
    for(i=1;(1<<i)<=k;i++){
        for(j=1;j<=k;j++){
            a[i][j]=a[i-1][j],jv=((1<<(i-1))+j);
            if(jv<=k && E[a[i][j]].second>=E[a[i-1][jv]].second)
                a[i][j]=a[i-1][jv];
        }
    }

    for(i=1;i<=z;i++){
        A[i].assign(4*(nr[i]),0);
        build(i,1,1,nr[i]);
    }
    for(i=1;i<=m;i++){
        f>>t>>x>>y;
        if(t==1){
            //x1=LT[poz[x]][nr[poz[x]]];
            //y1=LT[poz[y]][nr[poz[y]]];
            x1=F[x],y1=F[y];
            if(x1>y1) swap(x1,y1);
            b=p[y1-x1+1];
            jv=(y1-(1<<b)+1);
            if(E[a[b][x1]].second<=E[a[b][jv]].second)
                LCA=E[a[b][x1]].first;
            else LCA=E[a[b][jv]].first;
            if(poz[x]==poz[y]){
                q1=query(poz[x],1,1,nr[poz[x]],min(loc[x],loc[y]),max(loc[x],loc[y]));
                g<<V[q1]<<"\n";
                continue;
            }

            q1=q2=0;
            while(poz[x]!=poz[LCA]){
                q=query(poz[x],1,1,nr[poz[x]],1,loc[x]);
                if(V[q1]<V[q]) q1=q;
                x=T[LT[poz[x]][1]];
            }
            q=query(poz[x],1,1,nr[poz[x]],min(loc[x],loc[LCA]),max(loc[x],loc[LCA]));
            if(V[q1]<V[q]) q1=q;

            while(poz[y]!=poz[LCA]){
                q=query(poz[y],1,1,nr[poz[y]],1,loc[y]);
                if(V[q2]<V[q]) q2=q;
                y=T[LT[poz[y]][1]];
            }
            q=query(poz[y],1,1,nr[poz[y]],min(loc[y],loc[LCA]),max(loc[y],loc[LCA]));
            if(V[q2]<V[q]) q2=q;

            g<<max(V[q1],V[q2])<<"\n";
        }
        else{
            V[x]=y;
            update(poz[x],1,1,nr[poz[x]],loc[x],y);
        }
    }
    f.close();
    g.close();
    return 0;
}