Cod sursa(job #2742889)

Utilizator Sho10Andrei Alexandru Sho10 Data 22 aprilie 2021 10:54:01
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.24 kb
#include <bits/stdc++.h> //Andrei Alexandru a.k.a Sho
#define ll long long
#define double long double
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#define aint(a) (a).begin(), (a).end()
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define pi pair
#define rc(s) return cout<<s,0
#define endl '\n'
#define mod 1000000007
#define PI 3.14159265359
#define INF 1000000005
#define LINF 1000000000000000005ll
#define CODE_START  ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
ll n,q,a[200005],depth[200005],c[200005],roof[200005],lvl[200005],decc[200005],tree[800005],sz[200005],sub[200005],indx;
vector<ll>g[200005];
vector<ll>path[100005];
void dfs(ll node,ll par){
ll check=1;
sub[node]=1;
ll heavy=-1;
for(auto it : g[node]){
    if(it!=par){
        check=0;
        depth[it]=depth[node]+1;
        dfs(it,node);
        sub[node]+=sub[it];
        if(heavy==-1){
            heavy=it;
        }else if(sub[it]>sub[heavy]){
        heavy=it;
        }
    }
}
if(check){
    c[node]=++indx;
    sz[indx]++;
    path[indx].pb(node);
    return;
}
c[node]=c[heavy];
sz[c[node]]++;
path[c[node]].pb(node);
for(auto it : g[node]){
    if(it==heavy||depth[it]<depth[node]){
        continue;
    }else {
    roof[c[it]]=node;
    lvl[c[it]]=depth[node];
    }
}
}
void build(ll node,ll l,ll r,ll lant,ll decalaj){
if(l==r){
    tree[node+decalaj]=a[path[lant][l-1]];
    return;
}
ll mid=(l+r)/2;
build(2*node,l,mid,lant,decalaj);
build(2*node+1,mid+1,r,lant,decalaj);
tree[node+decalaj]=max(tree[2*node+decalaj],tree[2*node+1+decalaj]);
}
void update(ll node,ll l,ll r,ll pos,ll val,ll decalaj){
if(l==r){
    tree[node+decalaj]=val;
    return;
}
ll mid=(l+r)/2;
if(pos<=mid){
    update(2*node,l,mid,pos,val,decalaj);
}else {
update(2*node+1,mid+1,r,pos,val,decalaj);
}
tree[node+decalaj]=max(tree[2*node+decalaj],tree[2*node+1+decalaj]);
}
ll query(ll node,ll l,ll r,ll st,ll dr,ll decalaj){
if(l>dr){
    return 0;
}
if(r<st){
    return 0;
}
if(st<=l&&r<=dr){
    return tree[node+decalaj];
}
ll mid=(l+r)/2;
return max(query(2*node,l,mid,st,dr,decalaj),query(2*node+1,mid+1,r,st,dr,decalaj));
}
int32_t main(){
CODE_START;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin>>n>>q;
for(ll i=1;i<=n;i++)
{
    cin>>a[i];
}
for(ll i=1;i<n;i++)
{
    ll l,r;
    cin>>l>>r;
    g[l].pb(r);
    g[r].pb(l);
}
depth[1]=1;
dfs(1,0);
for(ll i=1;i<=indx;i++)
{
    reverse(path[i].begin(),path[i].end());
}
for(ll i=1;i<=indx;i++)
{
    if(i>1){
        decc[i]=decc[i-1]+sz[i-1]*4;
    }
    build(1,1,sz[i],i,decc[i]);
}
while(q--){
    ll type,x,y;
    cin>>type>>x>>y;
    if(type==0){
        update(1,1,sz[c[x]],depth[x]-lvl[c[x]],y,decc[c[x]]);
    }else {
    ll ans=0;
    while(true){
        if(c[x]==c[y]){
        if(depth[x]>depth[y]){
            swap(x,y);
        }
        ans=max(ans,query(1,1,sz[c[x]],depth[x]-lvl[c[x]],depth[y]-lvl[c[y]],decc[c[x]]));
        break;
    }else {
    if(lvl[c[x]]<lvl[c[y]]){
        swap(x,y);
    }
    ans=max(ans,query(1,1,sz[c[x]],1,depth[x]-lvl[c[x]],decc[c[x]]));
    x=roof[c[x]];
    }
    }
    cout<<ans<<endl;
    }
}
}