Cod sursa(job #1067874)

Utilizator Al3ks1002Alex Cociorva Al3ks1002 Data 27 decembrie 2013 16:46:04
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.04 kb
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int NMAX = 100005;
int i,N,M,X,Y,Paths,T,poz,val,A,B,Sol;
int Val[NMAX],SubArb[NMAX],Lant[NMAX],Father[NMAX],Lev[NMAX],Poz[NMAX];
vector<int> V[NMAX],P[NMAX],Arb[NMAX];
void Read()
{
    freopen("heavypath.in","r",stdin);
	freopen("heavypath.out","w",stdout);
	scanf("%d%d",&N,&M);
	for(i=1;i<=N;i++) scanf("%d",&Val[i]);
	for(i=1;i<N;i++)
	{
	    scanf("%d%d",&X,&Y);
	    V[X].push_back(Y);
	    V[Y].push_back(X);
	}
}
void DFS(int Node,int Niv,int Dad)
{
    SubArb[Node]=1; Lev[Node]=Niv;
    for(vector<int>::iterator it=V[Node].begin();it!=V[Node].end();it++)
        if(*it!=Dad)
        {
            Father[*it]=Node;
            DFS(*it,Niv+1,Node);
            SubArb[Node]+=SubArb[*it];
        }

    if(V[Node].size()==1 && Node!=1)
    {
        Lant[Node]=++Paths; P[Paths].push_back(0);
        P[Paths].push_back(Node); Poz[Node]=1; return;
    }

    int MaxSon=0;
    for(vector<int>::iterator it=V[Node].begin();it!=V[Node].end();it++)
        if(*it!=Dad && SubArb[*it]>SubArb[MaxSon]) MaxSon=*it;
    Lant[Node]=Lant[MaxSon];
    P[Lant[Node]].push_back(Node);
    Poz[Node]=P[Lant[Node]].size()-1;
}
void Build(int Node,int Left,int Right,int Path)
{
    if(Left==Right) {Arb[Path][Node]=Val[P[Path][Left]]; return;}
    int Middle=(Left+Right)/2;
    int LS=2*Node; int RS=LS+1;
    Build(LS,Left,Middle,Path);
    Build(RS,Middle+1,Right,Path);
    Arb[Path][Node]=max(Arb[Path][LS],Arb[Path][RS]);
}
void Update(int Node,int Left,int Right,int Path)
{
    if(Left==Right) {Arb[Path][Node]=val; return;}
    int Middle=(Left+Right)/2;
    int LS=2*Node; int RS=LS+1;
    if(poz<=Middle) Update(LS,Left,Middle,Path);
    else Update(RS,Middle+1,Right,Path);
    Arb[Path][Node]=max(Arb[Path][LS],Arb[Path][RS]);
}
void Query(int Node,int Left,int Right,int Path)
{
    if(Left>=A && Right<=B) {Sol=max(Sol,Arb[Path][Node]); return;}
    int Middle=(Left+Right)/2;
    int LS=2*Node; int RS=LS+1;
    if(A<=Middle) Query(LS,Left,Middle,Path);
    if(B>Middle) Query(RS,Middle+1,Right,Path);
}
int FindMax(int X,int Y)
{
    Sol=0;
    for(;;)
    {
        if(Lant[X]==Lant[Y])
        {
            A=min(Poz[X],Poz[Y]);
            B=max(Poz[X],Poz[Y]);
            Query(1,1,P[Lant[X]].size()-1,Lant[X]);
            break;
        }
        if(Lev[P[Lant[X]][1]]<Lev[P[Lant[Y]][1]]) swap(X,Y);
        A=1; B=Poz[X]; Query(1,1,P[Lant[X]].size()-1,Lant[X]);
        X=Father[P[Lant[X]][1]];
    }
    return Sol;
}
void Solve()
{
    DFS(1,1,0);
	for(i=1;i<=Paths;i++)
	{
	    reverse(P[i].begin()+1,P[i].end());
	    Arb[i].resize(4*(P[i].size())+5);
	    Build(1,1,P[i].size()-1,i);
	}
	for(i=1;i<=N;i++) Poz[i]=P[Lant[i]].size()-Poz[i];
	for(;M;M--)
	{
	    scanf("%d%d%d",&T,&X,&Y);
        if(T) printf("%d\n",FindMax(X,Y));
        else
        {
            poz=Poz[X]; val=Y;
            Update(1,1,P[Lant[X]].size()-1,Lant[X]);
        }
	}
}
int main()
{
	Read();
	Solve();
	return 0;
}