Cod sursa(job #1206269)

Utilizator IonMosnoiIon Mosnoi IonMosnoi Data 9 iulie 2014 13:20:15
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.37 kb
#include<fstream>
#include<algorithm>
#include<vector>
using namespace std;
ifstream f("heavypath.in");
ofstream o("heavypath.out");

vector <int> a[100100],b[100100];
int v[100100],n,m,k=0,path[100010],l[100100],tata[100100],idpath[1000100],def[1000100],arb[4000000],idar[100100],parc[100100];

void df(int nod,int v){
	l[nod] = v;
	if(a[nod].size()==1 && nod!=1){
		k++;
		b[k].push_back(nod);
	    path[nod]=k;
	    idpath[k]=v;
		idar[nod]=0;
		return;
	}
	parc[nod]=1;
	int maxim = -1;
	for(int i=0;i<a[nod].size();i++)
	 if(parc[a[nod][i]]!=1){
	 	df(a[nod][i],v+1);
	 	if(maxim==-1)maxim=a[nod][i];
	 	else{
	 		if(idpath[path[a[nod][i]]]==idpath[path[maxim]]){
	 			if(path[a[nod][i]]<path[maxim])maxim=a[nod][i];
	 		}else{
	 			if(idpath[path[a[nod][i]]]>idpath[path[maxim]])maxim=a[nod][i];
	 		}
	 		
	 	}
	 	tata[path[a[nod][i]]]=nod;
	 }
	 path[nod] = path[maxim];
	 b[path[maxim]].push_back(nod);
	 idar[nod] = b[path[maxim]].size()-1;
	 tata[path[maxim]]=0;
	parc[nod]=0;
}

void init(int x,int d,int l,int r,int nod=1){
	 if(r==l){
	 	arb[d+nod]=v[b[x][l]];
	 	return;
	 }
	 int m=(l+r)/2;
	 init(x,d,l,m,nod*2);
	 init(x,d,m+1,r,nod*2+1);
	 arb[d+nod] = max(arb[d+nod*2+1],arb[d+nod*2]);
}

void make_tree(){
	int d=0;
	for(int i=1;i<=k;i++){
		def[i]=d;
		d+=(b[i].size())*4+1;
		init(i,def[i],0,b[i].size()-1);
	}
}



void update(int x,int val,int i,int l,int r,int d,int nod){
	if(l==r){
		arb[nod+d] = val;
		return;
	}
	int m = (l+r)/2;
	if(x<=m)update(x,val,i,l,m,d,nod*2);
	else update(x,val,i,m+1,r,d,nod*2+1);
	arb[d+nod] = max(arb[d+nod*2+1],arb[d+nod*2]);
}

int query(int q,int p,int d,int l,int r,int nod){
	if(q<=l && p>=r)return arb[nod+d];
	int m = (l+r)/2,rs=-1;
	if(m>=q)rs = query(q,p,d,l,m,nod*2);
	if(m+1<=p)rs = max(rs,query(q,p,d,m+1,r,nod*2+1));
	return rs;
}


int lca(int x,int y){
	if(idpath[path[x]]==idpath[path[y]]){
				if(path[x]<path[y])swap(x,y);
			}else if(idpath[path[x]]>idpath[path[y]])swap(x,y);//x e mai jos ca y in arbore
//	o<<x<<" "<<y<<endl;
	int stop=1,rs=-1;
	while(stop){
		if(path[x]==path[y]){
			stop=0;
			if(l[x]<l[y])swap(x,y);//x e mai jos ca y in arbore
			rs = max(rs,query(idar[x],idar[y],def[path[x]],0,b[path[x]].size()-1,1));
		//	o<<x<<" "<<y<<endl;
		}else{
			rs = max(rs,query(idar[x],idar[b[path[x]][b[path[x]].size()-1]],def[path[x]],0,b[path[x]].size()-1,1));
			x = tata[path[x]];
		//	o<<x<<" "<<y<<endl;
			if(idpath[path[x]]==idpath[path[y]]){
				if(path[x]<path[y])swap(x,y);
			}else if(idpath[path[x]]>idpath[path[y]])swap(x,y);
			
		}
	}
//	o<<endl;
	return rs;
}

int main(){
	f>>n>>m;
	for(int i=1;i<=n;i++)f>>v[i];
	int x,y,z;
	for(int i=1;i<n;i++){
		f>>x>>y;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	df(1,1);
	make_tree();
/*
	for(int i=1;i<=k;i++){
		o<<i<<" "<<def[i]<<" "<<tata[i]<<" "<<idpath[i]<<endl;
		for(int j=0;j<b[i].size();j++)o<<b[i][j]<<" ";
		o<<endl;
	}
	for(int i=1;i<=n;i++)o<<path[i]<<" ";o<<endl;
	for(int i=1;i<=n;i++)o<<idar[i]<<" ";o<<endl;
	for(int i=1;i<=n;i++)o<<l[i]<<" ";o<<endl;
	for(int i=1;i<=4*n;i++)o<<arb[i]<<" ";o<<endl;*/
	//return 0;
	for(int i=1;i<=m;i++){
		f>>x;
		if(x){
			f>>z>>y;
			o<<lca(z,y)<<"\n";
		}else{
			f>>z>>y;
			update(idar[z],y,path[z],0,b[path[z]].size()-1,def[path[z]],1);
		//	for(int i=1;i<=4*n;i++)o<<arb[i]<<" ";o<<endl;
			}
	}
}