Cod sursa(job #3347090)

Utilizator Sorin_GabrielGabara Sorin Gabriel Sorin_Gabriel Data 15 martie 2026 16:06:56
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.34 kb
#include <bits/stdc++.h>
#define INF 1e8+1
#define VMAX 100005
//#define int long long int
using namespace std;

ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
int n;
int top[VMAX];
int sz[VMAX];
int tin[VMAX];
int heavy[VMAX];
vector<int> graf[VMAX];
int timer=0;
int depth[VMAX];
int tata[VMAX];

void decomp(int nod, int crt_top)
{
    tin[nod]=++timer;
    top[nod]=crt_top;

    if(heavy[nod])
    {
        decomp(heavy[nod],nod); // cobor in fiul heavy
    }
    for(auto it:graf[nod])
    {
        if(tin[it])
            continue;
        decomp(it,it); // it devine noul top
    }
}


void dfs(int nod, int parinte)
{
    tata[nod]=parinte;
    sz[nod]=1;
    int maxim=0;

    for(auto it:graf[nod])
    {
        if(it==parinte)
            continue;

        depth[it]=depth[nod]+1;
        dfs(it,nod);
        if(sz[it]>sz[maxim])
            maxim=it;
        sz[nod]+=sz[it];
    }

    heavy[nod]=maxim;
}



int aint[4*VMAX];
int val_init[VMAX];

void update(int st, int dr, int poz, int nr, int val)
{
    if(st==dr)
    {
        aint[nr]=val;
        return;
    }

    int mij = (st+dr)/2;

    if(poz<=mij)
        update(st,mij,poz,2*nr,val);
    else
        update(mij+1,dr,poz,2*nr+1,val);

    aint[nr]=max(aint[2*nr],aint[2*nr+1]);

}


int query(int st, int dr, int st_interv, int dr_interv, int nr)
{
    if(st_interv<=st && dr<=dr_interv)
        return aint[nr];

    int mij = (st+dr)/2,maxim=-INF;

    if(mij>=st_interv)
        maxim = max(maxim,query(st,mij,st_interv,dr_interv,2*nr));

    if(mij+1<=dr_interv)
        maxim=max(maxim,query(mij+1,dr,st_interv,dr_interv,2*nr+1));

    return maxim;
}

int get_lca(int u, int v) {
    // Jump from chain to chain until both nodes are on the same heavy path
    while (top[u] != top[v]) {
        // Always move the node whose chain head is deeper in the tree
        if (depth[top[u]] > depth[top[v]]) {
            u = tata[top[u]];
        } else {
            v = tata[top[v]];
        }
    }

    // Once they are on the same chain, the one with the smaller depth is the LCA
    if (depth[u] < depth[v]) return u;
    return v;
}


int get_max_hld(int inc, int fin)
{
    int maxim=-INF;
    while(depth[top[inc]]>=depth[fin])
    {
        // iau tot lantul heavy
        maxim=max(maxim,query(1,n,tin[top[inc]],tin[inc],1));
        inc = top[inc];

        if(inc==fin)
            break;

        inc = tata[inc];
    }

    // de la inc la fin
    maxim=max(maxim,query(1,n,tin[fin],tin[inc],1));
    return maxim;
}

int main()
{
    int m,i,j,k,t,q,nr,minim,maxim,suma, lca;

    fin>>n>>m;
    for(i=1;i<=n;i++)
    {
        fin>>val_init[i];
    }

    for(i=1;i<n;i++)
    {
        fin>>j>>k;
        graf[j].push_back(k);
        graf[k].push_back(j);
    }


    tin[0]=VMAX;
    dfs(1,0);
    decomp(1,1);


    for(i=1;i<=n;i++)
    {
        update(1,n,tin[i],1,val_init[i]);
    }




    while(m--)
    {
        fin>>i>>j>>k;
        if(i==0)
        {
            update(1,n,tin[j],1,k);
        }
        else
        {
            lca=get_lca(j,k);
            maxim=get_max_hld(j,lca);
            maxim=max(maxim,get_max_hld(k,lca));
            fout<<maxim<<'\n';
        }
    }


    return 0;
}