Cod sursa(job #2839006)

Utilizator BalasaRaduBalasa Radu BalasaRadu Data 25 ianuarie 2022 08:28:43
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.13 kb
#include <bits/stdc++.h>
using namespace std;

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


const int dim=100009;

vector<int>v[dim];///pentru arborele final
vector<int>sz,parent;

////////////////////////////////////////////////////////////////////////pentru lca
int len;
bool vizitat[dim];
vector<int> euler,aparitie,nivel;

void DFS(int x,int tata){
    euler[++len]=x;
    nivel[x]=nivel[tata]+1;
    aparitie[x]=len;
    for(int y:v[x]){
        if(y!=parent[x]){
            DFS(y,x);
            euler[++len]=x;
        }
    }
}
struct SegmentTreeMinim{
    struct Nod{
        int val,poz;
    }aint[4*dim];
    Nod Merge(Nod n1,Nod n2){
        if(n1.val<n2.val){
            return n1;
        }
        return n2;
    }
    void update(int nod,int tl,int tr,int poz,Nod x){
        if(tl==tr){
            aint[nod].val=x.val;
            aint[nod].poz=x.poz;
            return;
        }
        int tm=(tl+tr)/2;
        if(poz<=tm){
            update(2*nod,tl,tm,poz,x);
        }
        else{
            update(2*nod+1,tm+1,tr,poz,x);
        }
        aint[nod]=Merge(aint[2*nod],aint[2*nod+1]);
    }
    Nod 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 Merge(query(2*nod,tl,tm,l,tm),query(2*nod+1,tm+1,tr,tm+1,r));
    }
}B;
void find_lca(){
    DFS(1,0);
    for(int i=1;i<=len;i++){
        B.update(1,1,len,i,{nivel[euler[i]],euler[i]});
    }
}
int lca(int a,int b){
    a=aparitie[a];
    b=aparitie[b];
    if(a>b){
        swap(a,b);
    }
    return B.query(1,1,len,a,b).poz;
}
////////////////////////////////////////////////////////////////////////

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

struct SegmentTreeMaxim{
    int aint[4*dim];
    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));
    }
}A;

int nr_comp;///nr total de componenete

vector<int>comp,val,poz_aint;
vector<int>c[dim];///nodurile care se afla in comp i

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

signed main(){
    int n,q;
        fin>>n>>q;

        euler = vector<int>(2*n+9);
        aparitie = vector<int>(2*n+9);
        nivel = vector<int>(n+9);
        comp = vector<int>(n+9);
        val = vector<int>(n+9);
        poz_aint = vector<int>(n+9);
        sz = vector<int>(n+9);
        parent = vector<int>(n+9);

    for(int i=1;i<=n;i++){
        fin>>val[i];
    }
    for(int i=2;i<=n;i++){
        int x,y;
        fin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs_size(1,0);
    find_lca();
    HPD(1,1,0);

    int total=0;
    for(int i=1;i<=nr_comp;i++){
        for(int x:c[i]){
            total++;
            poz_aint[x]=total;
            A.update(1,1,n,total,val[x]);
        }
    }

    while(q--){
        int op;
            fin>>op;
        if(op==0){
            int poz,val;
            fin>>poz>>val;
            A.update(1,1,n,poz_aint[poz],val);
        }
        else{
            int l,r;
            fin>>l>>r;
            int comun=lca(l,r);
            int ans=0;
            while(comp[l]!=comp[comun]){
                ans=max(ans,A.query(1,1,n,poz_aint[c[comp[l]][0]],poz_aint[l]));
                l=parent[c[comp[l]][0]];
            }
            ans=max(ans,A.query(1,1,n,poz_aint[comun],poz_aint[l]));
            while(comp[r]!=comp[comun]){
                ans=max(ans,A.query(1,1,n,poz_aint[c[comp[r]][0]],poz_aint[r]));
                r=parent[c[comp[r]][0]];
            }
            ans=max(ans,A.query(1,1,n,poz_aint[comun],poz_aint[r]));
            fout<<ans<<'\n';
        }
    }
}