Cod sursa(job #2414735)

Utilizator AndreiDeltaBalanici Andrei Daniel AndreiDelta Data 24 aprilie 2019 23:05:27
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.11 kb
#include <bits/stdc++.h>
#define Dim 100009
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
void query();
int N,M,x,a,b,dx[Dim],val[Dim],cnt=1,T;
int label[Dim],poz[Dim],roof[Dim],Deep[2*Dim+10],Euler[2*Dim+10],First[Dim];
int rmq[18][2*Dim+10],Level[Dim],lca,cont_chain;
int ID_chain[Dim],Tree[4*Dim+10],numara,MAX;
int LIMA,LIMB,supremlider,vertex;
bool viz[Dim],viz2[Dim],viz3[Dim];

vector <int> V[Dim];
vector < pair<int,int> > Lant[Dim];

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

void Build_chain(int nod,int index)
{
    viz2[nod]=1;
    poz[nod]=index;
    label[nod]=cnt;
    Lant[cnt].push_back({nod,index});
    pair <int,int> which;
    for(unsigned int i=0;i<V[nod].size();i++)
    {
        int vecin=V[nod][i];
        if(!viz2[vecin])
        if(dx[vecin]>which.first) which={dx[vecin],vecin};
        if(i==V[nod].size()-1)
        {
            Build_chain(which.second,index+1);
        }
    }

    for(unsigned int i=0;i<V[nod].size();i++)
    {
        int vecin=V[nod][i];
        if(!viz2[vecin]&&vecin!=which.second)
        {
            cnt++;
            roof[cnt]=nod;
            Build_chain(vecin,1);
        }
    }

}

void DFS(int nod,int level)
{
    viz3[nod]=1;
    Level[nod]=level;

    Euler[++cnt]=nod;
    Deep[cnt]=level;
    First[nod]=cnt;

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

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

    for(int i=1;(1<<i)<=cnt;i++)
    for(int j=1;j+(1<<i)-1<=cnt;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 LCA(int X,int Y)
{
    int prim1=First[X];
    int prim2=First[Y];
    if(prim1>prim2) swap(prim1,prim2);

    int dif=log2(prim2-prim1+1);
    int care1=rmq[dif][prim1];
    int care2=rmq[dif][prim2-(1<<dif)+1];
    if(Deep[care1]<=Deep[care2])
       return Euler[care1];
    else
       return Euler[care2];
}

void Build(int nod,int st,int dr)
{
    if(st==dr)
    {
        Tree[nod+ID_chain[T]]=val[Lant[T][++numara].first];
        return;
    }
    int mij=(st+dr)/2;
    Build(2*nod,st,mij);
    Build(2*nod+1,mij+1,dr);
    Tree[nod+ID_chain[T]]=max(Tree[2*nod+ID_chain[T]],Tree[2*nod+1+ID_chain[T]]);
}

void query(int nod,int st,int dr,int defazaj)
{
    if(st>=LIMA&&dr<=LIMB)
    {
        supremlider=max(Tree[nod+defazaj],supremlider);
        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);

}

void Solve(int X,int Y)
{
    bool ok=1;
    while(ok)
    {
        if(label[X]==label[Y])
        {
            LIMA=poz[X]; LIMB=poz[Y];

            supremlider=0;
            query(1,1,Lant[label[X]].size(),ID_chain[label[X]]);
            //if(T==6) cout<<X<<" "<<Y<<" "<<LIMA<<" "<<LIMB<<" "<<label[X]<<" "<<ID_chain[label[X]]<<'\n';
            MAX=max(MAX,supremlider);
            ok=0;
            return;
        }
         else
        {
           LIMA=1; LIMB=poz[Y];
           supremlider=0;
           query(1,1,Lant[label[Y]].size(),ID_chain[label[Y]]);
           MAX=max(MAX,supremlider);
           Y=roof[label[Y]];
        }
    }
}

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

    int mij=(st+dr)/2;
    if(a<=mij)
    Update(2*nod,st,mij,defazaj);
    else
    Update(2*nod+1,mij+1,dr,defazaj);
    Tree[nod+defazaj]=max(Tree[2*nod+defazaj],Tree[2*nod+1+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_nod(1);
    roof[1]=1;
    Build_chain(1,1);
    cont_chain=cnt;   cnt=0;
    DFS(1,1);
    RMQ();

    for(int i=1;i<=cont_chain;i++) Lant[i].erase(Lant[i].begin()+Lant[i].size());

/*for(T=1;T<=cont_chain;T++)
{
    cout<<roof[T]<<'\n';
    for(int i=0;i<Lant[T].size();i++) cout<<Lant[T][i].first<<" "<<Lant[T][i].second<<'\n';
    cout<<'\n'<<'\n';
} cout<<label[2]<<" "<<label[9]<<'\n';

*/

    for(T=1;T<=cont_chain;T++)
    {
        numara=-1;
        if(T>1) ID_chain[T]=ID_chain[T-1]+4*Lant[T].size();
        Build(1,1,Lant[T].size());
    }

    for(T=1;T<=M;T++)
    {
        f>>x>>a>>b;
        lca=LCA(a,b);

        if(x)
        {
            MAX=0;
            Solve(lca,a);
            Solve(lca,b);
            g<<MAX<<'\n';
        }
        else
        {
            Update(1,1,Lant[label[a]].size(),ID_chain[label[a]]);
        }
    }

    return 0;
}