Cod sursa(job #936571)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 7 aprilie 2013 19:31:53
Problema Heavy Path Decomposition Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 2.88 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;

#define NMAX 100001

vector <int> v[NMAX],p[NMAX],a[4*NMAX+1];
int whatpath[NMAX],whatpoz[NMAX],weight[NMAX],niv[NMAX],parent[NMAX],viz[NMAX],tata[NMAX],val[NMAX],nrp,rez,path,poz,vval;

void dfs(int nod)
{
	int fiu;
	bool frunza;
	viz[nod]=1;
	frunza=1;
	fiu=0;
	weight[nod]=1;
	for(vector <int> :: iterator it=v[nod].begin();it!=v[nod].end();it++)
		if(viz[*it]==0) {
			frunza=0;
			niv[*it]=niv[nod]+1;
			dfs(*it);
			tata[*it]=nod;
			weight[nod]=weight[nod]+weight[*it];
			if(fiu==0)
				fiu=*it;
			else if(weight[*it]>weight[fiu])
				fiu=*it;
		}
	if(frunza) {
		nrp++;
		whatpath[nod]=nrp;
		p[nrp].push_back(nod);
	}
	else {
		p[whatpath[fiu]].push_back(nod);
		whatpath[nod]=whatpath[fiu];
	}
}

void built(int nod, int st, int dr, int path)
{
	int mij;
	if(st==dr) {
		a[path][nod]=val[p[path][st]];
		return ;
	}
	mij=(st+dr)/2;
	built(nod*2,st,mij,path);
	built(nod*2+1,mij+1,dr,path);
	a[path][nod]=max(a[path][nod*2],a[path][nod*2+1]);
}

void makepaths()
{
	int i;
	dfs(1);
	for(i=1;i<=nrp;i++) {
		reverse(p[i].begin(),p[i].end());
		for(vector <int> :: iterator it=p[i].begin();it!=p[i].end();it++) 
			whatpoz[*it]=it-p[i].begin();
		a[i].resize(4*p[i].size());
		built(1,0,p[i].size()-1,i);
		parent[i]=tata[*p[i].begin()];
	}
}

void update(int nod, int st, int dr)
{
	int mij;
	if(st==dr) {
		a[path][nod]=vval;
		return ;
	}
	mij=(st+dr)/2;
	if(poz<=mij)
		update(nod*2,st,mij);
	else update(nod*2+1,mij+1,dr);
	a[path][nod]=max(a[path][nod*2],a[path][nod*2+1]);
}

void query(int nod, int st, int dr, int first, int second, int path)
{
	int mij;
	if(first<=st && dr<=second) {
		rez=max(rez,a[path][nod]);
		return ;
	}
	mij=(st+dr)/2;
	if(first<=mij)
		query(nod*2,st,mij,first,second,path);
	if(mij<second)
		query(nod*2+1,mij+1,dr,first,second,path);
}

int which(int x, int y)
{
	if(whatpath[x]==whatpath[y]) {
		rez=-1;
		query(1,0,p[whatpath[x]].size()-1,min(whatpoz[x],whatpoz[y]),max(whatpoz[x],whatpoz[y]),whatpath[x]);
		return rez;
	}
	int p1,p2,val;
	p1=whatpath[x];
	p2=whatpath[y];
	if(niv[parent[p1]]>niv[parent[p2]] || (niv[parent[p1]]==niv[parent[p2]] && parent[p2]==0)) {
		swap(x,y);
		swap(p1,p2);
	}
	rez=-1;
	query(1,0,p[whatpath[y]].size()-1,0,whatpoz[y],whatpath[y]);
	val=rez;
	return max(val,which(x,parent[p2]));
}

int main ()
{
	int n,m,i,x,y,opt;
	ifstream f("heavypath.in");
	ofstream g("heavypath.out");
	f>>n>>m;
	for(i=1;i<=n;i++)
		f>>val[i];
	for(i=1;i<=n-1;i++) {
		f>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	makepaths();
	for(i=1;i<=m;i++) {
		f>>opt>>x>>y;
		if(opt==0) {
			poz=whatpoz[x];
			vval=y;
			path=whatpath[x];
			update(1,0,p[whatpath[x]].size()-1);
		}
		else g<<which(x,y)<<'\n';
	}
	f.close();
	g.close();
	return 0;
}