Cod sursa(job #2416693)

Utilizator AndreiDeltaBalanici Andrei Daniel AndreiDelta Data 27 aprilie 2019 21:45:39
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.8 kb
#include <bits/stdc++.h>
#define Dim 100010
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
ifstream lop("aux.in");
ofstream h("aux.out");
int N,M,Val[Dim],Poz[Dim],Roof[Dim],Label[Dim],DX[Dim],A,B;
int cnt=1,cont,Euler[3*Dim],Deep[3*Dim],rmq[18][3*Dim],First[Dim];
int op,lca,Gap[Dim],Tree[4*Dim],numara,ans,Max,LimA,LimB;
bool viz[Dim];

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

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

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

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

    pair <int,int> which;

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

        if(i==V[nod].size()-1) Decomposition(which.first,index+1);
    }

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

void DFS_Oiler(int nod,int level)
{
    viz[nod]=1;
    Euler[++cont]=nod;
    Deep[cont]=level;
    First[nod]=cont;

    for(unsigned int i=0;i<V[nod].size();i++)
    {
        int vecin=V[nod][i];
        if(!viz[vecin])
        {
            DFS_Oiler(vecin,level+1);
            Euler[++cont]=nod;
            Deep[cont]=level;
        }
    }
}

void RMQ()
{
    for(int i=1;i<=cont;i++) rmq[0][i]=i;

    for(int i=1;(1<<i)<=cont;i++)
    for(int j=1;j+(1<<i)-1<=cont;j++)
    {
        A=rmq[i-1][j];
        B=rmq[i-1][j+(1<<(i-1))];
        if(Deep[A]<=Deep[B]) rmq[i][j]=A;
        else rmq[i][j]=B;
    }
}

int Lowest(int X,int Y)
{
    int pozA=First[X];
    int pozB=First[Y];
    if(pozA>pozB) swap(pozA,pozB);

    int dif=log2(pozB-pozA+1);
    if(Deep[rmq[dif][pozA]]<=Deep[rmq[dif][pozB-(1<<dif)+1]]) return Euler[rmq[dif][pozA]];
    else return Euler[rmq[dif][pozB-(1<<dif)+1]];
}

void Build(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;
    Build(2*nod,st,mij,lant,defazaj);
    Build(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 lant,int defazaj)
{
    if(st==dr)
    {
        Tree[nod+defazaj]=B;
        return;
    }
    int mij=(st+dr)/2;

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

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

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

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

void Recursion(int X,int Y)
{

     if(Label[X]==Label[Y])
     {
         LimA=Poz[X]; LimB=Poz[Y];
         Max=0;
         Query(1,1,Chain[Label[X]].size(),Label[X],Gap[Label[X]]);
         ans=max(ans,Max);
         return;
     }
     else
     {
         LimA=1; LimB=Poz[Y];
         Max=0;

         Query(1,1,Chain[Label[Y]].size(),Label[Y],Gap[Label[Y]]);
         ans=max(ans,Max);
         Recursion(X,Roof[Label[Y]]);
     }
}


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_Count(1); init();
    Decomposition(1,1); init();

    /*for(int i=1;i<=cnt;i++)
    {
        cout<<Roof[i]<<'\n';
        for(unsigned int j=0;j<Chain[i].size();j++) cout<<Chain[i][j]<<" "<<Poz[Chain[i][j]]<<'\n';
        cout<<'\n'<<'\n';

    }*/

    DFS_Oiler(1,1); init();
    RMQ();

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

    for(int i=1;i<=M;i++)
    {
        f>>op>>A>>B;

        if(!op)
        {
            Update(1,1,Chain[Label[A]].size(),Label[A],Gap[Label[A]]);
        }
        else
        {
            lca=Lowest(A,B);
            ans=0;
            Recursion(lca,A);
            Recursion(lca,B);
            g<<ans<<'\n';
        }
    }

    return 0;
}