Cod sursa(job #3040883)

Utilizator hhhhhhhAndrei Boaca hhhhhhh Data 30 martie 2023 16:02:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.14 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n,m,val[100005],niv[100005],in[100005],out[100005];
vector<int> muchii[100005];
int where[100005],poz[100005];
int par[100005];
bool isheavy[100005];
int timp,nr[100005];
vector<vector<int>> arb;
vector<int> emp;
vector<vector<int>> path;
int lg[100005];
void dfs(int nod)
{
    timp++;
    in[nod]=timp;
    nr[nod]=1;
    for(int i:muchii[nod])
        if(i!=par[nod])
        {
            par[i]=nod;
            niv[i]=niv[nod]+1;
            dfs(i);
            nr[nod]+=nr[i];
        }
    out[nod]=timp;
    int who=0,maxim=0;
    for(int i:muchii[nod])
        if(i!=par[nod])
            if(nr[i]>maxim)
            {
                maxim=nr[i];
                who=i;
            }
    if(maxim>0)
        isheavy[who]=1;
}
void arbupdate(int ind,int nod,int st,int dr,int p,int x)
{
    if(st==dr)
    {
        arb[ind][nod]=x;
        return;
    }
    int mij=(st+dr)/2;
    if(p<=mij)
        arbupdate(ind,nod*2,st,mij,p,x);
    else
        arbupdate(ind,nod*2+1,mij+1,dr,p,x);
    arb[ind][nod]=max(arb[ind][nod*2],arb[ind][nod*2+1]);
}
int arbquery(int ind,int nod,int st,int dr,int a,int b)
{
    if(st>=a&&dr<=b)
        return arb[ind][nod];
    int mij=(st+dr)/2;
    int rez=0;
    if(a<=mij)
        rez=max(rez,arbquery(ind,nod*2,st,mij,a,b));
    if(b>mij)
        rez=max(rez,arbquery(ind,nod*2+1,mij+1,dr,a,b));
    return rez;
}
bool isancestor(int a,int b)
{
    return in[a]<=in[b]&&out[a]>=out[b];
}
void build()
{
    path.push_back(emp);
    arb.push_back(emp);
    int cnt=0;
    for(int start=1;start<=n;start++)
    {
        bool good=1;
        for(int i:muchii[start])
            if(i!=par[start])
                if(isheavy[i])
                    good=0;
        if(good)
        {
            vector<int> pp;
            cnt++;
            arb.push_back(emp);
            int nod=start;
            while(true)
            {
                pp.push_back(nod);
                if(isheavy[nod])
                    nod=par[nod];
                else
                    break;
            }
            for(int i=0;i<pp.size();i++)
            {
                where[pp[i]]=cnt;
                poz[pp[i]]=i+1;
            }
            int lg=pp.size();
            path.push_back(pp);
            arb[cnt].resize(4*lg+5);
        }
    }
}
void update(int nod,int val)
{
    int ind=where[nod];
    int p=poz[nod];
    arbupdate(ind,1,1,path[ind].size(),p,val);
}
int query(int a,int b)
{
    int rez=0;
    while(true)
    {
        int ind=where[a];
        int p=poz[a];
        if(!isancestor(path[ind].back(),b))
        {
            rez=max(rez,arbquery(ind,1,1,path[ind].size(),p,path[ind].size()));
            a=par[path[ind].back()];
            continue;
        }
        else
        {
            int st=p;
            int dr=path[ind].size();
            int last=1e9;
            while(st<=dr)
            {
                int mij=(st+dr)/2;
                if(isancestor(path[ind][mij-1],b))
                {
                    last=mij;
                    dr=mij-1;
                }
                else
                    st=mij+1;
            }
            rez=max(rez,arbquery(ind,1,1,path[ind].size(),p,last));
            break;
        }
    }
    return rez;
}
int main()
{
    ios_base::sync_with_stdio(false);
    fin.tie(0);
    fin>>n>>m;
    for(int i=1;i<=n;i++)
        fin>>val[i];
    for(int i=1;i<n;i++)
    {
        int a,b;
        fin>>a>>b;
        muchii[a].push_back(b);
        muchii[b].push_back(a);
    }
    niv[1]=1;
    dfs(1);
    build();
    for(int i=1;i<=n;i++)
        update(i,val[i]);
    while(m--)
    {
        int tip;
        fin>>tip;
        if(tip==0)
        {
            int nod,x;
            fin>>nod>>x;
            val[nod]=x;
            update(nod,x);
        }
        else
        {
            int a,b;
            fin>>a>>b;
            fout<<max(query(a,b),query(b,a))<<'\n';
        }
    }
    return 0;
}