Cod sursa(job #2460974)

Utilizator smoc_georgemarianSmoc George-Marian smoc_georgemarian Data 24 septembrie 2019 19:18:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.75 kb
#include <bits/stdc++.h>
#define NMAX 100009
#define LOG 40
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int val[NMAX];
int sizen[NMAX];
int pinc[NMAX];
int level[NMAX];
int fatherchain[NMAX];
int n,m,nrc,sol;
int v[NMAX];
int wchain[NMAX];///carui apartine
bool uz[NMAX];
vector <int>a[NMAX];
vector <int>g[NMAX];
vector <int>chain[NMAX];

void citire();
void query(int x,int y);
void dfs(int k, int tata);
void build(int chain, int nod, int st, int dr);
void update(int ch,int nod, int st, int dr, int poz, int val);
void query_aint(int ch, int nod, int st, int dr, int x, int y, int &maxi);
///astea sunt pentru caz simplu
int main()
{citire();
 dfs(1,0);
for(int i=1;i<=nrc;i++){
    for(int j=0;j<2*chain[i].size();j++)
         a[i].push_back(0);
    build(i,1,1,chain[i].size()-1);
}
///le am bilduit pe toate
for(int i=1;i<=m;i++)
    {
     int op,x,y;
     fin>>op>>x>>y;
     if(!op)
        update(wchain[x],1,1,chain[wchain[x]].size()-1,pinc[x],y);
       else
       {
        sol=0;
        query(x,y);
        fout<<sol<<'\n';
       }
    }
    return 0;
}
void citire()
{int i,x,y;
 fin>>n>>m;
 for(i=1;i<=n;i++)
        fin>>v[i];
 for(i=1;i<=n-1;i++)
    {
     fin>>x>>y;
     g[x].push_back(y);
     g[y].push_back(x);
    }
}
void dfs(int k, int tata)
{int i;bool ok=0;
 uz[k]=1;sizen[k]=1;level[k]=level[tata]+1;
 for(i=0;i<g[k].size();i++)
        if(!uz[g[k][i]])
           dfs(g[k][i],k),ok=1,sizen[k]+=sizen[g[k][i]];
 ///acum ca am pregatit pentru el vedem daca e fr
 if(!ok)///e frunza
    {
    chain[++nrc].push_back(0);
    chain[nrc].push_back(k);
    wchain[k]=nrc;
    pinc[k]=1;
    }
    else
    {
     int maxim=0;int poz=0;///pun direct fiul
     for(i=0;i<g[k].size();i++)
           if(g[k][i]!=tata)
            if(sizen[g[k][i]]>maxim) { maxim=sizen[g[k][i]];poz=g[k][i];}
     chain[wchain[poz]].push_back(k);
     wchain[k]=wchain[poz];
     pinc[k]=chain[wchain[poz]].size()-1;
     ///acum face parte din chain, e tata pt doar restul
     for(i=0;i<g[k].size();i++)
        if(g[k][i]!=tata && g[k][i]!=poz)
            fatherchain[wchain[g[k][i]]]=k;
    }
}

void build(int ch, int nod, int st, int dr)
{
  if(st==dr)
  {a[ch][nod]=v[chain[ch][st]];return;}
 int mj=(st+dr)/2;
 build(ch,2*nod,st,mj);
 build(ch,2*nod+1,mj+1,dr);
 a[ch][nod]=max(a[ch][2*nod],a[ch][2*nod+1]);
}
void update(int ch, int nod, int st, int dr, int poz, int val)
{
 if(st==dr)
 {a[ch][nod]=val;return;}
 int mj=(st+dr)/2;
 if(poz<=mj)
    update(ch,2*nod,st,mj,poz,val);
  else
    update(ch,2*nod+1,mj+1,dr,poz,val);
  a[ch][nod]=max(a[ch][2*nod],a[ch][2*nod+1]);

}
void query_aint(int ch, int nod, int st, int dr, int x, int y, int &maxi)
{
  if(x<=st && dr<=y)
    {maxi=max(maxi,a[ch][nod]);return;}
 int mj=(st+dr)/2;
 if(x<=mj)
    query_aint(ch,2*nod,st,mj,x,y,maxi);
if(y>mj)
    query_aint(ch,2*nod+1,mj+1,dr,x,y,maxi);
}
void query(int x,int y)
{
  if(wchain[x]==wchain[y])///caz banal
    {
     int maxi=0;
     int posx=pinc[x];
     int posy=pinc[y];
     if(posx>posy)
        swap(posx,posy);
     query_aint(wchain[x],1,1,chain[wchain[x]].size()-1,posx,posy,maxi);
     sol=max(sol,maxi);
     return;
    }
  if(level[fatherchain[wchain[x]]]>level[fatherchain[wchain[y]]])
    {
     int maxi=0;
     query_aint(wchain[x],1,1,chain[wchain[x]].size()-1,pinc[x],chain[wchain[x]].size()-1,maxi);
     sol=max(sol,maxi);
     int nr=fatherchain[wchain[x]];
     query(nr,y);
    }
    else
    {
      int maxi=0;
      query_aint(wchain[y],1,1,chain[wchain[y]].size()-1,pinc[y],chain[wchain[y]].size()-1,maxi);
      sol=max(sol,maxi);
      int nr=fatherchain[wchain[y]];
      query(x,nr);
    }
}