Cod sursa(job #2682547)

Utilizator etienAndrone Stefan etien Data 8 decembrie 2020 21:17:29
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.15 kb
#include<bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n,i,m;
vector<int>v[100001];
int nr[100001],t[100001],depth[100001],val[100001];
int lant[100001];
bool viz[100001];
int pozlant[100001];
vector<int>vallant[100001];
int nrv,poz[100001];
vector<int>arb[100001];
void dfst(int nod,int prt)
{
    for(auto q:v[nod])
    {
        if(q!=prt)
        {
            t[q]=nod;
            dfst(q,nod);
        }
    }
}
void dfs(int nod)
{
    for(auto q:v[nod])
    {
        if(q!=t[nod])
        {
            depth[q]=depth[nod]+1;
            dfs(q);
            nr[nod]+=nr[q];
        }
    }
    nr[nod]++;
}
void dfs2(int nod)
{
    if(lant[nod])
        return;
    int pop=-1;
    for(auto q:v[nod])
        if(q!=t[nod])
        {
            dfs2(q);
            if(pop<nr[q])
            {
                lant[nod]=lant[q];
                pop=nr[q];
            }
        }
}
void update(int poz,int nr,int st,int dr,int p,int pl)
{
    if(st==dr)
    {
        arb[pl][poz]=nr;
        return;
    }
    int mid=(st+dr)/2;
    if(p<=mid)
        update(poz*2,nr,st,mid,p,pl);
    else
        update(poz*2+1,nr,mid+1,dr,p,pl);
    arb[pl][poz]=max(arb[pl][poz*2],arb[pl][poz*2+1]);
}
int query(int qst,int qdr,int st,int dr,int poz,int pl)
{
    if(st>=qst&&dr<=qdr)
        return arb[pl][poz];
    if(st>qdr)
        return -1;
    if(dr<qst)
        return -1;
    int mid=(st+dr)/2;
    int a,b;
    a=query(qst,qdr,st,mid,poz*2,pl);
    b=query(qst,qdr,mid+1,dr,poz*2+1,pl);
    return max(a,b);
}
int main()
{
    fin>>n>>m;
    for(i=1;i<=n;i++)
        fin>>val[i];
    for(i=1;i<n;i++)
    {
        int a,b;
        fin>>a>>b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    dfst(1,0);
    dfs(1);
    for(int i=2;i<=n;i++)
        if(v[i].size()==1)
            lant[i]=i;
    dfs2(1);
    for(int i=2;i<=n;i++)
    {
        if(v[i].size()==1)
        {
            int nod=i;
            while(lant[t[nod]]==lant[i])
                nod=t[nod];
            int nod2=i;
            while(nod2!=t[nod])
            {
                viz[nod2]=true;
                pozlant[nod2]=depth[nod2]-depth[nod]+1;
                lant[nod2]=nod;
                nod2=t[nod2];
            }
        }
    }
    fill(viz,viz+100001,0);
    for(int i=2;i<=n;i++)
    {
        if(v[i].size()==1)
        {
            nrv++;
            int nod=i;
            while(lant[nod]==lant[i])
            {
                vallant[nrv].push_back(val[nod]);
                viz[nod]=true;
                poz[nod]=nrv;
                nod=t[nod];
            }
        }
    }
    for(int i=1;i<=nrv;i++)
    {
        for(int j=0;j<(vallant[i].size()+1)/2;j++)
            swap(vallant[i][j],vallant[i][vallant[i].size()-1-j]);
        for(auto q:vallant[i])
        {
            for(int j=1;j<=5;j++)
            {
                arb[i].push_back(0);
            }
        }
    }
    for(int i=1;i<=nrv;i++)
    {
        for(int j=0;j<vallant[i].size();j++)
        {
            update(1,vallant[i][j],1,vallant[i].size(),j+1,i);
        }
    }
    for(int i=1;i<=m;i++)
    {
        int op,a,b;
        fin>>op>>a>>b;
        if(op==0)
        {
            update(1,b,1,vallant[poz[a]].size(),pozlant[a],poz[a]);
        }
        else
        {
            int maxim=0;
            while(lant[a]!=lant[b])
            {
                if(depth[lant[b]]>depth[lant[a]])
                {
                    maxim=max(maxim,query(1,pozlant[b],1,vallant[poz[b]].size(),1,poz[b]));
                    int tt=lant[b];
                    b=t[lant[b]];
                }
                else
                {
                    maxim=max(maxim,query(1,pozlant[a],1,vallant[poz[a]].size(),1,poz[a]));
                    a=t[lant[a]];
                }
            }
            if(pozlant[a]>pozlant[b])
                swap(a,b);
            maxim=max(maxim,query(pozlant[a],pozlant[b],1,vallant[poz[a]].size(),1,poz[a]));
            fout<<maxim<<"\n";
        }
    }
}