Cod sursa(job #3333162)

Utilizator vladneaguVladneagu vladneagu Data 11 ianuarie 2026 16:22:29
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.33 kb
#include <fstream>
#include <algorithm>
#include <iomanip>
#include <vector>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int maxn=1e3+5;
vector<int> adj[maxn];
int vals[maxn];
int val[maxn];
int tin[maxn];
int tout[maxn];
int poznod[maxn];
int primul[maxn];
int fvval[maxn];
int subtree[maxn];
int binary_lift[maxn][17];
vector<vector<int>> aint;
int cnt=1;
int cnt2=1;
int n,q;
void dfs(int nod,int par) {
    subtree[nod]=1;
    binary_lift[nod][0]=par;
    tin[nod]=cnt2++;
    int maxsubtree=0,valmax=0;
    for (auto elem:adj[nod]) {
        if (elem!=par) {
            dfs(elem,nod);
            subtree[nod]+=subtree[elem];
            if (subtree[elem]>maxsubtree) {
                maxsubtree=subtree[elem];
                valmax=val[elem];
            }
        }
    }
    if (maxsubtree == 0) {
        val[nod]=cnt++;
    }else val[nod]=valmax;
    tout[nod]=cnt2++;
}
void update(int nod,int l,int r,int poz,int val,int grupa) {
    if (l>poz || r<poz)return;
    if (l==poz && r==poz) {
        aint[grupa][nod]=val;
        return;
    }
    int mid=(l+r)/2;
    update(nod*2,l,mid,poz,val,grupa);
    update(nod*2+1,mid+1,r,poz,val,grupa);
    aint[grupa][nod]=max(aint[grupa][nod*2],aint[grupa][nod*2+1]);
}
int query(int nod,int l,int r,int st,int dr,int grupa) {
    if (l>dr || r<st)return 0;
    if (l>=st && r<=dr)return aint[grupa][nod];
    int mid=(l+r)/2;
    return max(query(nod*2,l,mid,st,dr,grupa),query(nod*2+1,mid+1,r,st,dr,grupa));
}
bool isancestor(int nod1,int nod2) {
    return (tin[nod1]<=tin[nod2] && tout[nod1]>=tout[nod2]);
}
void dfs2(int nod,int par) {
    fvval[val[nod]]++;
    if (primul[val[nod]]==0)primul[val[nod]]=nod;
    poznod[nod]=fvval[val[nod]];
    for (auto elem:adj[nod]) {
        if (elem!=par) {
            dfs2(elem,nod);
        }
    }
}
int lca(int u,int v) {
    if (isancestor(u,v))return u;
    if (isancestor(v,u))return v;
    int nod=u;
    for (int i=16;i>=1;i--) {
        if (isancestor(binary_lift[nod][i],v)==0 && binary_lift[nod][i]!=0) {
            nod=binary_lift[nod][i];
        }
    }
    return binary_lift[nod][0];
}
int solve(int nod1,int nod2) {
    if (val[nod1]==val[nod2]) {
        return query(1,1,fvval[val[nod1]],min(poznod[nod1],poznod[nod2]),max(poznod[nod1],poznod[nod2]),val[nod1]);
    }
    int z;
    int nod3=primul[val[nod1]];
    z=query(1,1,fvval[val[nod1]],poznod[nod3],poznod[nod1],val[nod1]);
    return max(solve(binary_lift[primul[val[nod1]]][0],nod2),z);
}
signed main() {
    cin>>n>>q;
    for (int i=1;i<=n;i++) {
        cin>>vals[i];
    }
    for (int i=1;i<n;i++) {
        int l,r;
        cin>>l>>r;
        adj[l].push_back(r);
        adj[r].push_back(l);
    }
    dfs(1,0);
    dfs2(1,0);
    aint.resize(cnt+1);
    for (int j=1;j<=16;j++) {
        for (int i=1;i<=n;i++) {
            binary_lift[i][j]=binary_lift[binary_lift[i][j-1]][j-1];
        }
    }
    for (int i=1;i<=cnt-1;i++) {
        aint[i].resize(4*fvval[i]+1);
    }
    for (int i=1;i<=n;i++) {
        int gr=val[i];
        update(1,1,fvval[gr],poznod[i],vals[i],gr);
    }
    while (q--) {
        int t,x,y;
        cin>>t>>x>>y;
        if (t==0) {
            int gr=val[x];
            update(1,1,fvval[gr],poznod[x],y,gr);
        }else {
            int lcaa=lca(x,y);
            cout<<max(solve(x,lcaa),solve(y,lcaa))<<'\n';
        }
    }
    return 0;
}