Cod sursa(job #1755588)

Utilizator PopoviciRobertPopovici Robert PopoviciRobert Data 10 septembrie 2016 17:11:15
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.14 kb
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#define MAXN 100000
std::vector <int> G[MAXN+1];
std::vector <int> L[MAXN+1];
int father[MAXN+1],val[MAXN+1];
int lant[MAXN+1];
int dp[MAXN+1];
int poz[MAXN+1];
int lvl[MAXN+1];
int *aint[MAXN+1];
inline void add_Edge(int a,int b){
   G[a].push_back(b);
}
int con;
void DFS1(int nod){
    int i,maxim,nr;
    if(G[nod].size()==0){
       ++con;
       lant[nod]=con;
       dp[nod]=1;
    }
    else{
       maxim=0;
       dp[nod]=1;
       for(i=0;i<G[nod].size();i++){
          DFS1(G[nod][i]);
          if(dp[G[nod][i]]>maxim){
            nr=lant[G[nod][i]];
            maxim=dp[G[nod][i]];
          }
          dp[nod]+=dp[G[nod][i]];
       }
       lant[nod]=nr;
    }
}
void DFS2(int nod){
    int i;
    L[lant[nod]].push_back(nod);
    poz[nod]=L[lant[nod]].size()-1;
    for(i=0;i<G[nod].size();i++){
       lvl[G[nod][i]]=lvl[nod]+1;
       DFS2(G[nod][i]);
    }
}
inline int getmax(int a,int b){
    if(a<b) return b;
    return a;
}
inline int getmin(int a,int b){
   if(a<b) return a;
   return b;
}
void update(int nod,int left,int right,int poz,int val,int nr){
     if(left==right)
         aint[nr][nod]=val;
     else{
         int med=(left+right)/2;
         if(poz<=med)
           update(2*nod,left,med,poz,val,nr);
         else
           update(2*nod+1,med+1,right,poz,val,nr);
         aint[nr][nod]=getmax(aint[nr][2*nod],aint[nr][2*nod+1]);
     }
}
int max;
void query(int nod,int left,int right,int l,int r,int nr){
     if(l<=left&&right<=r){
        if(max<aint[nr][nod])
          max=aint[nr][nod];
     }
     else{
        int med=(left+right)/2;
        if(l<=med)
          query(2*nod,left,med,l,r,nr);
        if(med<r)
          query(2*nod+1,med+1,right,l,r,nr);
     }
}
int main(){
   FILE*fi,*fout;
   int i,n,m,a,b,root,t,x,y,ans,aux;
   fi=fopen("heavypath.in" ,"r");
   fout=fopen("heavypath.out" ,"w");
   fscanf(fi,"%d %d " ,&n,&m);
   for(i=1;i<=n;i++)
     fscanf(fi,"%d " ,&val[i]);
   for(i=1;i<n;i++){
      fscanf(fi,"%d %d " ,&a,&b);
      add_Edge(a,b);
      father[b]=a;
   }
   i=1;
   while(father[i]>0)
     i++;
   root=i;
   con=0;
   DFS1(root);
   for(i=0;i<=con;i++)
     L[i].push_back(0);
   lvl[root]=1;
   DFS2(root);
   for(i=1;i<=con;i++){
      aint[i]=(int *) malloc(sizeof(int)*4*L[i].size());
      memset(aint[i],0,sizeof(aint[i]));
   }
   for(i=1;i<=n;i++)
      update(1,1,L[lant[i]].size()-1,poz[i],val[i],lant[i]);
   while(m>0){
      m--;
      fscanf(fi,"%d %d %d " ,&t,&x,&y);
      if(t==0)
        update(1,1,L[lant[x]].size()-1,poz[x],y,lant[x]);
      else{
        ans=0;
        while(lant[x]!=lant[y]){
           if(lvl[L[lant[x]][1]]<lvl[L[lant[y]][1]]){
              aux=x;
              x=y;
              y=aux;
           }
           max=0;
           query(1,1,L[lant[x]].size()-1,1,poz[x],lant[x]);
           if(max>ans)
             ans=max;
           x=father[L[lant[x]][1]];
        }
        max=0;
        query(1,1,L[lant[x]].size()-1,getmin(poz[x],poz[y]),getmax(poz[x],poz[y]),lant[x]);
        if(max>ans)
          ans=max;
        fprintf(fout,"%d\n" ,ans);
      }
   }
   fclose(fi);
   fclose(fout);
   return 0;
}