Cod sursa(job #2838976)

Utilizator BalasaRaduBalasa Radu BalasaRadu Data 24 ianuarie 2022 23:09:26
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.78 kb
#include <bits/stdc++.h>
using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");


const int dim=100009;

vector<int>g[dim];///folosit doar la inceput
vector<int>v[dim];///pentru arborele final

////////////////////////////////////////////////////////////////////////pentru lca
int len,nivel[dim];
int euler[2*dim],aparitie[2*dim];
int logaritm[2*dim],rmq[2*dim][20];
void DFS(int x,int tata){
    euler[++len]=x;
    nivel[x]=nivel[tata]+1;
    aparitie[x]=len;
    for(int y:v[x]){
        DFS(y,x);
        euler[++len]=x;
    }
}
void generare(){
    for(int i=2;i<=len;i++){
        logaritm[i]=logaritm[i/2]+1;
    }
    for(int i=1;i<=len;i++){
        rmq[i][0]=i;
    }
    for(int j=1;(1<<j)<=len;j++){
        for(int i=1;i+(1<<j)-1<=len;i++){
            int l=rmq[i][j-1];
            int r=rmq[i+(1<<(j-1))][j-1];
            rmq[i][j]=(nivel[euler[l]]<nivel[euler[r]]) ? l : r;
        }
    }
}
int lca(int a,int b){
    a=aparitie[a];
    b=aparitie[b];
    if(a>b){
        swap(a,b);
    }
    int log=logaritm[b-a+1];
    int l=rmq[a][log];
    int r=rmq[b-(1<<log)+1][log];
    return (nivel[euler[l]]<nivel[euler[r]]) ? euler[l] : euler[r];
}
void find_lca(){
    DFS(1,0);
    generare();
}
////////////////////////////////////////////////////////////////////////

bool vizitat[dim];
int sz[dim],parent[dim];

void dfs_size(int x,int tata){
    vizitat[x]=1;
    sz[x]=1;
    for(int y:g[x]){
        if(!vizitat[y]){
            dfs_size(y,x);
            parent[y]=x;
            v[x].push_back(y);
            sz[x]+=sz[y];
        }
    }
}

struct SegmentTree{
    vector<int>aint;
    void init(int lungime){
        for(int i=0;i<=4*lungime;i++){
            aint.push_back(0);
        }
    }
    void update(int nod,int tl,int tr,int poz,int val){
        if(tl==tr){
            aint[nod]=val;
            return;
        }
        int tm=(tl+tr)/2;
        if(poz<=tm){
            update(2*nod,tl,tm,poz,val);
        }
        else{
            update(2*nod+1,tm+1,tr,poz,val);
        }
        aint[nod]=max(aint[2*nod],aint[2*nod+1]);
    }
    int query(int nod,int tl,int tr,int l,int r){
        if(l==tl && r==tr){
            return aint[nod];
        }
        int tm=(tl+tr)/2;
        if(r<=tm){
            return query(2*nod,tl,tm,l,r);
        }
        if(l>tm){
            return query(2*nod+1,tm+1,tr,l,r);
        }
        return max(query(2*nod,tl,tm,l,tm),query(2*nod+1,tm+1,tr,tm+1,r));
    }
}aint[dim];

int nr_comp;///nr total de componenete
int comp[dim];///componenta int care se afla nodul x
int len_comp[dim];///lungimea componenetei i
int poz_comp[dim];///pozitia in componenta a lui x
int cap_comp[dim];///capul componenei i
int val[dim];

void HPD(int x,bool schimba,int comp_tata){///generare lanturi HPD
    int comp_locala;
    if(schimba){
        nr_comp++;
        comp_locala=nr_comp;
        cap_comp[comp_locala]=x;
    }
    else{
        comp_locala=comp_tata;
    }
    comp[x]=comp_locala;
    len_comp[comp_locala]++;
    poz_comp[x]=len_comp[comp_locala];
    for(int y:v[x]){
        if(sz[y]>sz[x]/2||v[x].size()==1){
            HPD(y,0,comp_locala);
        }
        else{
            HPD(y,1,comp_locala);
        }
    }
}

bool initializat[dim];

signed main(){
    int n,q;
        fin>>n>>q;
    for(int i=1;i<=n;i++){
        fin>>val[i];
    }
    for(int i=2;i<=n;i++){
        int x,y;
        fin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs_size(1,0);
    find_lca();
    HPD(1,1,0);
    for(int i=1;i<=n;i++){
        if(!initializat[comp[i]]){
            aint[comp[i]].init(len_comp[comp[i]]);
            initializat[comp[i]]=true;
        }
        aint[comp[i]].update(1,1,len_comp[comp[i]],poz_comp[i],val[i]);
    }
    while(q--){
        int op;
            fin>>op;
        if(op==0){
            int poz,val;
            fin>>poz>>val;
            aint[comp[poz]].update(1,1,len_comp[comp[poz]],poz_comp[poz],val);
        }
        else{
            int l,r;
            fin>>l>>r;
            int c=lca(l,r);
            int ans=0;
            while(comp[l]!=comp[c]){
                ans=max(ans,aint[comp[l]].query(1,1,len_comp[comp[l]],1,poz_comp[l]));
                l=parent[cap_comp[comp[l]]];
            }
            ans=max(ans,aint[comp[l]].query(1,1,len_comp[comp[l]],poz_comp[c],poz_comp[l]));
            while(comp[r]!=comp[c]){
                ans=max(ans,aint[comp[r]].query(1,1,len_comp[comp[r]],1,poz_comp[r]));
                r=parent[cap_comp[comp[r]]];
            }
            ans=max(ans,aint[comp[r]].query(1,1,len_comp[comp[r]],poz_comp[c],poz_comp[r]));
            fout<<ans<<endl;
        }
    }
}