Cod sursa(job #2418318)

Utilizator AndreiDeltaBalanici Andrei Daniel AndreiDelta Data 4 mai 2019 16:34:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.38 kb
#include <bits/stdc++.h>
#define Dim 100010
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int N,M,Val[Dim],a,b,DX[Dim],cnt=1,Label[Dim],Poz[Dim],Roof[Dim];
int Tree[4*Dim],Gap[Dim],numara,op,x,y,ans,LimA,LimB,Level[Dim];
bool viz[Dim];

vector <int> V[Dim],Chain[Dim];

void init()
{
    for(int i=1;i<=N;i++) viz[i]=0;
}

void DFS(int nod,int lvl)
{
    viz[nod]=1;
    Level[nod]=lvl;
    for(unsigned int i=0;i<V[nod].size();i++)
    {
        int vecin=V[nod][i];
        if(!viz[vecin])
        {
            DFS(vecin,lvl+1);
            DX[nod]+=DX[vecin];
        }
    }
}

void Build(int nod,int index)
{
    viz[nod]=1;
    Label[nod]=cnt;
    Poz[nod]=index;
    Chain[cnt].push_back(nod);

    pair <int,int> pii;

    for(unsigned int i=0;i<V[nod].size()&&DX[nod]!=1;i++)
    {
        int vecin=V[nod][i];
        if(!viz[vecin]&&DX[vecin]>pii.second) pii={vecin,DX[vecin]};
        if(i==V[nod].size()-1) Build(pii.first,index+1);
    }

    for(unsigned int i=0;i<V[nod].size();i++)
    {
        int vecin=V[nod][i];
        if(!viz[vecin])
        {
            cnt++;
            Roof[cnt]=nod;
            Build(vecin,1);
        }
    }
}

void Make(int nod,int st,int dr,int lant,int defazaj)
{
    if(st==dr)
    {
        numara++;
        Tree[nod+defazaj]=Val[Chain[lant][numara]];
        return;
    }
    int mij=(st+dr)/2;
    Make(2*nod,st,mij,lant,defazaj);
    Make(2*nod+1,mij+1,dr,lant,defazaj);
    Tree[nod+defazaj]=max(Tree[2*nod+defazaj],Tree[2*nod+1+defazaj]);
}

void Update(int nod,int st,int dr,int defazaj)
{
    if(st==dr)
    {
        Tree[nod+defazaj]=y;
        return;
    }

    int mij=(st+dr)/2;
    if(Poz[x]<=mij)
    Update(2*nod,st,mij,defazaj);
    if(Poz[x]>=mij+1)
    Update(2*nod+1,mij+1,dr,defazaj);

    Tree[nod+defazaj]=max(Tree[2*nod+defazaj],Tree[2*nod+1+defazaj]);
}

void Query(int nod,int st,int dr,int defazaj)
{
    if(st>=LimA&&dr<=LimB)
    {
        ans=max(ans,Tree[nod+defazaj]);
        return;
    }
    int mij=(st+dr)/2;

    if(LimA<=mij)
    Query(2*nod,st,mij,defazaj);
    if(LimB>=mij+1)
    Query(2*nod+1,mij+1,dr,defazaj);
}

int main()
{
    f>>N>>M;
    for(int i=1;i<=N;i++)
    {
        f>>Val[i];
        DX[i]=1;
    }
    for(int i=1;i<N;i++)
    {
        f>>a>>b;
        V[a].push_back(b);
        V[b].push_back(a);
    }
    DFS(1,1); init();
    Build(1,1); init();

    for(int i=1;i<=cnt;i++)
    {
        numara=-1;
        if(i>1) Gap[i]=Gap[i-1]+4*Chain[i-1].size();
        Make(1,1,Chain[i].size(),i,Gap[i]);
    }

    for(int i=1;i<=M;i++)
    {
        f>>op>>x>>y;
        if(!op)
        {
            Update(1,1,Chain[Label[x]].size(),Gap[Label[x]]);
        }
        else
        {
            ans=0;
            while(Label[x]!=Label[y])
            {
                if(Level[Roof[Label[x]]]<Level[Roof[Label[y]]]) swap(x,y);
                LimA=1; LimB=Poz[x];
                Query(1,1,Chain[Label[x]].size(),Gap[Label[x]]);
                x=Roof[Label[x]];
            }

            if(Label[x]==Label[y])
            {
                if(Poz[x]>Poz[y]) swap(x,y);
                LimA=Poz[x]; LimB=Poz[y];
                Query(1,1,Chain[Label[x]].size(),Gap[Label[x]]);
            }
            g<<ans<<'\n';
        }
    }

    return 0;
}