Cod sursa(job #2773029)

Utilizator hhhhhhhAndrei Boaca hhhhhhh Data 4 septembrie 2021 11:32:40
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.03 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n,m,val[100005],par[100005],nr[100005],isheavy[100005],nrpath,what[100005],dp[18][100005],niv[100005];
int pathpar[100005],poz[100005],lg[100005];
int in[100005],out[100005],timp;
vector<vector<int>> arb;
vector<int> muchii[100005];
vector<int> path[100005];
void update(int index,int nod,int st,int dr,int poz,int val)
{
    if(st==dr)
    {
        arb[index][nod]=val;
        return;
    }
    int mij=(st+dr)/2;
    if(poz<=mij)
        update(index,nod*2,st,mij,poz,val);
    else
        update(index,nod*2+1,mij+1,dr,poz,val);
    arb[index][nod]=max(arb[index][nod*2],arb[index][nod*2+1]);
}
int query(int index,int nod,int st,int dr,int a,int b)
{
    if(st>=a&&dr<=b)
        return arb[index][nod];
    int mij=(st+dr)/2;
    int rez=0;
    if(a<=mij)
        rez=max(rez,query(index,nod*2,st,mij,a,b));
    if(b>mij)
        rez=max(rez,query(index,nod*2+1,mij+1,dr,a,b));
    return rez;
}
void dfs(int nod)
{
    timp++;
    in[nod]=timp;
    nr[nod]=1;
    if(niv[nod]==0)
        niv[nod]=1;
    dp[0][nod]=par[nod];
    for(int i=1;i<=17;i++)
        dp[i][nod]=dp[i-1][dp[i-1][nod]];
    for(auto i:muchii[nod])
        if(i!=par[nod])
        {
            niv[i]=niv[nod]+1;
            par[i]=nod;
            dfs(i);
            nr[nod]+=nr[i];
        }
    for(auto i:muchii[nod])
        if(i!=par[nod])
            if(nr[i]>=nr[nod]/2+nr[nod]%2)
                isheavy[i]=1;
    timp++;
    out[nod]=timp;
}
bool isancestor(int x,int y)
{
    return niv[x]<=niv[y]&&in[x]<=in[y]&&out[x]>=out[y];
}
int lca(int x,int y)
{
    if(niv[x]>niv[y])
        swap(x,y);
    if(isancestor(x,y))
        return x;
    for(int i=17;i>=0;i--)
        if(dp[i][x]!=0&&!isancestor(dp[i][x],y))
            x=dp[i][x];
    return par[x];
}
int getmax(int y,int x)
{
    int rez=0;
    while(true)
    {
        if(what[y]==what[x])
        {
            rez=max(rez,query(what[y],1,1,lg[what[y]],poz[y],poz[x]));
            y=x;
            break;
        }
        else
        {
            rez=max(rez,query(what[y],1,1,lg[what[y]],poz[y],lg[what[y]]));
            y=pathpar[what[y]];
        }
    }
    return rez;
}
int main()
{
    ios_base::sync_with_stdio(false);
    fin.tie(0);
    fout.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);
    }
    dfs(1);
    for(int i=1;i<=n;i++)
    {
        bool found=0;
        int nod=i;
        for(auto j:muchii[nod])
            if(j!=par[nod])
                if(isheavy[j]==1)
                    found=1;
        if(found==0)
        {
            nrpath++;
            path[nrpath].push_back(nod);
            what[nod]=nrpath;
            while(isheavy[nod])
            {
                nod=par[nod];
                what[nod]=nrpath;
                path[nrpath].push_back(nod);
            }
        }
    }
    vector<int> a;
    arb.push_back(a);
    for(int i=1;i<=nrpath;i++)
    {
        a.clear();
        //reverse(path[i].begin(),path[i].end());
        lg[i]=path[i].size();
        for(int j=0;j<=2*path[i].size();j++)
            a.push_back(0);
        arb.push_back(a);
        for(int j=0;j<path[i].size();j++)
        {
            poz[path[i][j]]=j+1;
            pathpar[i]=par[path[i][j]];
        }
    }
    for(int i=1;i<=n;i++)
        update(what[i],1,1,lg[what[i]],poz[i],val[i]);
    while(m--)
    {
        bool ok=0;
        int tip,x,y;
        fin>>tip>>x>>y;
        if(m==9)
            ok=1;
        if(tip==0)
            update(what[x],1,1,lg[what[x]],poz[x],y);
        else
        {
            int LCA=lca(x,y);
            int rez=max(getmax(x,LCA),getmax(y,LCA));
            if(rez==0)
                ok=1;
            fout<<rez<<'\n';
        }
    }
    return 0;
}