Cod sursa(job #642913)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 2 decembrie 2011 16:08:38
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.86 kb
#include<fstream>
#include<vector>
#include<algorithm>
#define NMAX 100100
using namespace std;
vector <int> G[NMAX],SirElem[NMAX];
int n,nr_sir;
int v[NMAX],aint[4*NMAX],poz[NMAX];
int nivel[NMAX],fii[NMAX],lant[NMAX],tata[NMAX];
bool viz[NMAX];
int query(int nod,int left,int right,int a,int b,int decalaj) {
	if(a<=left&&right<=b)
		return aint[nod+decalaj];
	int mid=(left+right)>>1,rez=0;
	if(a<=mid)
		rez=query(2*nod,left,mid,a,b,decalaj);
	if(b>mid)
		rez=max(rez,query(2*nod+1,mid+1,right,a,b,decalaj));
	return rez;
}
void update(int nod,int left,int right,int poz,int decalaj,int val) {
	if(left==right) {
		aint[nod+decalaj]=val;
		return;
		}
	int mid=(left+right)>>1;
	if(poz<=mid)
		update(2*nod,left,mid,poz,decalaj,val);
	else
		update(2*nod+1,mid+1,right,poz,decalaj,val);
	
	aint[nod+decalaj]=max(aint[2*nod+decalaj],aint[2*nod+1+decalaj]);
}
void build(int nod,int left,int right,int decalaj,int lant) {
	if(left==right) {
		aint[nod+decalaj]=v[SirElem[lant][left-1]];
		return;
		}
	int mid=(left+right)>>1;
	build(2*nod,left,mid,decalaj,lant);
	build(2*nod+1,mid+1,right,decalaj,lant);
	
	aint[nod+decalaj]=max(aint[2*nod+decalaj],aint[2*nod+1+decalaj]);
}
void dfs(int nod) {
	int i,vecin,best=-1;
	viz[nod]=1;
	fii[nod]=1;
	for(i=0;i<G[nod].size();i++) {
		vecin=G[nod][i];
		if(viz[vecin])
			continue;
		nivel[vecin]=nivel[nod]+1;
		dfs(vecin);
		fii[nod]+=fii[vecin];
		if(best==-1)
			best=vecin;
		else
		if(fii[best]<fii[vecin])
			best=vecin;
		}
	
	if(fii[nod]==1) {
		lant[nod]=++nr_sir;
		SirElem[nr_sir].push_back(nod);
		return;
		}
	
	lant[nod]=lant[best];
	SirElem[lant[best]].push_back(nod);
	
	for(i=0;i<G[nod].size();i++)
		if(G[nod][i]!=best)
			tata[lant[G[nod][i]]]=nod;
}	
void make_paths() {
	int i;
	nivel[1]=1;
	dfs(1);
	for(i=1;i<=nr_sir;i++) {
		reverse(SirElem[i].begin(),SirElem[i].end());
		poz[i]=poz[i-1]+SirElem[i-1].size()*4;
		build(1,1,SirElem[i].size(),poz[i],i);
		}
}
int main() {
	int i,t,x,y,m,sol;
	ifstream in("heavypath.in");
	ofstream out("heavypath.out");
	in>>n>>m;
	for(i=1;i<=n;in>>v[i++]);
	for(i=1;i<n;i++) {
		in>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
		}
	make_paths();
	
	for(i=0;i<m;i++) {
		in>>t>>x>>y;
		if(t==0)
			update(1,1,SirElem[lant[x]].size(),nivel[x]-nivel[tata[lant[x]]],poz[lant[x]],y);
		else {
			sol=1;
			while( true ) {
				if(lant[x]==lant[y]) {
					if(nivel[x]>nivel[y])
						swap(x,y);
					sol=max(sol,query(1,1,SirElem[lant[x]].size(),nivel[x]-nivel[tata[lant[x]]],nivel[y]-nivel[tata[lant[y]]],poz[lant[x]]));
					break;
					}
				if(nivel[tata[lant[x]]]<nivel[tata[lant[y]]])
					swap(x,y);
				sol=max(sol,query(1,1,SirElem[lant[x]].size(),1,nivel[x]-nivel[tata[lant[x]]],poz[lant[x]]));
				x=tata[lant[x]];
				}
			out<<sol<<'\n';
			}
		}
	in.close();
	out.close();
	return 0;
}