Cod sursa(job #3168700)

Utilizator Raul_AArdelean Raul Raul_A Data 13 noiembrie 2023 08:33:16
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.36 kb
#include <bits/stdc++.h>
#define eb emplace_back
#define ll long long
#define cin in
#define cout out
#define pii pair<int,int>
#define eb emplace_back
using namespace std;

const string file_name("heavypath");

ifstream in(file_name + ".in");
ofstream out(file_name + ".out");

const int MAX=1e5;

int n,k,a[MAX+5],first[MAX+5],niv[MAX+5],L[MAX+5],Lfather[MAX+5],len,Lniv[MAX+5];
int w[MAX+5],nrL,Tree[4*MAX+5],Ldecal[MAX+5];
vector<int> G[MAX+5];
bitset<MAX+5> p;
vector<int> Lant[2*MAX+5];

void read()
{
    cin>>n>>k;

    for(int i=1;i<=n;i++)
        cin>>a[i];

    for(int i=1,x,y;i<n;i++)
    {
        cin>>x>>y;
        G[x].eb(y);
        G[y].eb(x);
    }
}

void dfs(int node)
{
    p[node]=1;
    w[node]=1;
    int maxl=-1,leaf=1;

    for(auto x: G[node])
    {
        if(p[x]) continue;

        niv[x]=niv[node]+1;
        leaf=0;
        dfs(x);
        w[node]+=w[x];
        if(maxl==-1) maxl=x;
        else if(w[maxl]<w[x]) maxl=x;
    }

    if(leaf)
    {
        nrL++;
        L[node]=nrL;
        Lant[L[node]].eb(node);
        return;
    }
    L[node]=L[maxl];
    Lant[L[node]].eb(node);

    for(auto x: G[node])
    {
        if(x==maxl or niv[x]<niv[node]) continue;
        Lfather[L[x]]=node;
        Lniv[L[x]]=niv[node];
    }
}

void build(int node,int l,int r,int decal,int pozl)
{
    if(l==r)
    {
        Tree[node+decal]=a[Lant[pozl][l-1]];
    }
    else
    {
        int m=(l+r)/2;
        build(2*node,l,m,decal,pozl);
        build(2*node+1,m+1,r,decal,pozl);

        Tree[node+decal]=max(Tree[2*node+decal],Tree[2*node+1+decal]);
    }
}

void make_paths()
{
    niv[1]=1;
    dfs(1);

    for(int i=1;i<=nrL;i++)
    {
        reverse(Lant[i].begin(),Lant[i].end());

        if(i!=1)
            Ldecal[i]=Ldecal[i-1]+Lant[i-1].size()*4;

        build(1,1,Lant[i].size(),Ldecal[i],i);
    }
}

void update(int node,int l,int r,int poz,int val,int decal)
{
    if(l==r)
        Tree[node+decal]=val;
    else
    {
        int m=(l+r)/2;
        if(poz<=m)
            update(2*node,l,m,poz,val,decal);
        else update(2*node+1,m+1,r,poz,val,decal);

        Tree[node+decal]=max(Tree[2*node+decal],Tree[2*node+1+decal]);
    }
}

int query(int node,int l,int r,int a,int b,int decal)
{
    if(a<=l and r<=b)
        return Tree[node+decal];
    else
    {
        int m=(l+r)/2;
        int left=INT_MIN,right=INT_MIN;

        if(a<=m) left=query(2*node,l,m,a,b,decal);
        if(b>m) right=query(2*node+1,m+1,r,a,b,decal);

        return max(left,right);
    }
}

void solve()
{
    int t,x,y;

    cin>>t>>x>>y;

    if(t==0)
    {
        update(1,1,Lant[L[x]].size(),niv[x]-Lniv[L[x]],y,Ldecal[L[x]]);
    }
    else
    {
        int ans=INT_MIN;
        while(1)
        {
            if(L[x]==L[y])
            {
                if(niv[x]>niv[y]) swap(x,y);
                ans=max(ans,query(1,1,Lant[L[x]].size(),niv[x]-Lniv[L[x]],niv[y]-Lniv[L[y]],Ldecal[L[x]]));
                break;
            }
            if(Lniv[x]>Lniv[y]) swap(x,y);

            ans=max(ans,query(1,1,Lant[L[x]].size(),1,niv[x]-Lniv[L[x]],Ldecal[L[x]]));
            x=Lfather[L[x]];
        }
        cout<<ans<<'\n';
    }
}

int main()
{
    read();
    make_paths();
    while(k--) solve();
    return 0;
}