Cod sursa(job #933098)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 29 martie 2013 16:49:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.24 kb
#include <fstream>
#include <algorithm>
#include <vector>
#define nmax 100100
#define Vecin G[Nod][i]
#define Position(x) (Level[x]-Level[Father[Lant[x]]])
using namespace std;

vector <int> G[nmax],LantElementar[nmax];
int N,Q,Value[nmax],Level[nmax],Fii[nmax],Lant[nmax];
int NrLant,Father[nmax],Start[nmax],Ai[4*nmax];
bool used[nmax];

void Update(int Nod,int Left,int Right,int X,int Decalaj,int value) {
	
	if(Left == Right) {
		Ai[Nod+Decalaj]=value;
		return;
		}
	
	int Mid=(Left+Right)>>1;
	
	if(X<=Mid) Update(Nod<<1,Left,Mid,X,Decalaj,value);
	else Update((Nod<<1)|1,Mid+1,Right,X,Decalaj,value);
	
	Ai[Nod+Decalaj]=max(Ai[(Nod<<1)+Decalaj],Ai[((Nod<<1)|1)+Decalaj]);
	
}
int Query(int Nod,int Left,int Right,int A,int B,int Decalaj) {
	
	if(A <= Left && Right <= B)
		return Ai[Nod+Decalaj];
	
	int Mid=(Left+Right)>>1,Answer=0;
	
	if(A<=Mid) Answer = Query(Nod<<1,Left,Mid,A,B,Decalaj);
	if(B>Mid) Answer = max (Answer, Query((Nod<<1)|1,Mid+1,Right,A,B,Decalaj));
	
	return Answer;
	
}
void Build(int Nod,int Left,int Right,int Decalaj,int lant) {
	
	if(Left == Right) {
		Ai[Nod+Decalaj]=Value[ LantElementar[lant][Left-1] ];
		return;
		}
	
	int Mid=(Left+Right)>>1;
	
	Build(Nod<<1,Left,Mid,Decalaj,lant);
	Build((Nod<<1)|1,Mid+1,Right,Decalaj,lant);
	
	Ai[Nod+Decalaj]=max(Ai[(Nod<<1)+Decalaj],Ai[((Nod<<1)|1)+Decalaj]);
	
}
void Dfs(int Nod) {
	
	int i,Fiu=0;
	
	used[Nod]=1;
	
	for(i=0;i<G[Nod].size();i++)
		if(!used[Vecin]) {
			
			Level[Vecin]=Level[Nod]+1;
			Dfs(Vecin);
			Fii[Nod]+=Fii[Vecin]+1;
			
			if(!Fiu || Fii[Fiu]<Fii[Vecin])
				Fiu=Vecin;
			
			}
		
	if(!Fii[Nod]) {
		Lant[Nod]=++NrLant;
		LantElementar[NrLant].push_back(Nod);
		return;
		}
	
	Lant[Nod]=Lant[Fiu];
	LantElementar[Lant[Nod]].push_back(Nod);
	
	for(i=0;i<G[Nod].size();i++)
		if(Vecin != Fiu && Level[Vecin] > Level[Nod])
			Father[ Lant[Vecin] ] = Nod;
	
}
void BuildPaths() {

	Level[1]=1;
	
	Dfs(1);
	
	for(int i=1;i<=NrLant;i++) {
		
		reverse(LantElementar[i].begin(),LantElementar[i].end());
		Start[i] = Start[i-1] + 4*LantElementar[i-1].size();
		Build(1,1,LantElementar[i].size(),Start[i],i);
		
		}

}
void read(ifstream & in) {

    int i,x,y;
	
	in>>N>>Q;
	
	for(i=1;i<=N;i++)
		in>>Value[i];
	
	for(i=1;i<N;i++) {
		
		in>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
		
		}

}
int main() {
	
	int tip,x,y,lant,Answer;
	ifstream in("heavypath.in");
	ofstream out("heavypath.out");

    read(in);
	BuildPaths();
	
	while(Q--) {
		
		in>>tip>>x>>y;
		
		if(tip == 0) {
			
			lant=Lant[x];
			Update(1,1,LantElementar[lant].size(),Position(x),Start[lant],y);
			
			}
		else {
			
			Answer=0;
			
			while( Lant[x] != Lant[y] ) {
				
				if(Level[Father[Lant[x]]] < Level[Father[Lant[y]]])
					swap(x,y);
				
				lant=Lant[x];
				Answer = max(Answer, Query(1,1,LantElementar[lant].size(),1,Position(x),Start[lant]));
				
				x = Father[lant];
				
				}
			
			lant = Lant[x];
				
			if(Level[x] > Level[y])
				swap(x,y);
				
			Answer = max(Answer, Query(1,1,LantElementar[lant].size(),Position(x),Position(y),Start[lant]));
			
			out<<Answer<<'\n';
			
			}
		
		}
	
	in.close();
	out.close();
	
    return 0;

}