Cod sursa(job #790497)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 21 septembrie 2012 16:41:53
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.56 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
#define pb push_back
const int NMAX = 100001;
const int MMAX = 100001;
const int LMAX = 19;
vector <int> v[NMAX],path[NMAX],arb[NMAX];
int subarb[NMAX],lant[NMAX],poz[NMAX],up[NMAX],val[NMAX],niv[NMAX],paths,valmax,k;
int a[LMAX][4*NMAX+1],p[4*NMAX+1],niv2[4*NMAX+1],poz2[4*NMAX+1],lg[4*NMAX+1];
void dfs(int nod, int parinte, int lev)
{
	int smax;
	subarb[nod]=1;
	niv[nod]=lev;
	p[++k]=nod;
	niv2[k]=lev;
	poz2[nod]=k;
	for(vector <int> :: iterator it=v[nod].begin();it!=v[nod].end();it++)
		if(*it!=parinte) {
			up[*it]=nod;
			dfs(*it,nod,lev+1);
			subarb[nod]=subarb[nod]+subarb[*it];
			p[++k]=nod;
			niv2[k]=lev;
		}
	if(v[nod].size()==1 && nod!=1) {
		path[++paths].pb(0);
		path[paths].pb(nod);
		lant[nod]=paths;
		poz[nod]=1;
		return ;
	}
	smax=0;
	for(vector <int> :: iterator it=v[nod].begin();it!=v[nod].end();it++)
		if(*it!=parinte && subarb[*it]>subarb[smax]) 
			smax=*it;
	lant[nod]=lant[smax];
	path[lant[smax]].pb(nod);
	poz[nod]=path[lant[smax]].size()-1;
}
void init(int nod, int st, int dr, int paths)
{
	int mij;
	if(st==dr) {
		arb[paths][nod]=val[path[paths][st]];
		return ;
	}
	mij=(st+dr)/2;
	init(nod*2,st,mij,paths);
	init(nod*2+1,mij+1,dr,paths);
	arb[paths][nod]=max(arb[paths][nod*2],arb[paths][nod*2+1]);
}
void update(int nod, int st, int dr, int paths, int qpoz, int y)
{
	int mij;
	if(st==dr) {
		arb[paths][nod]=y;
		return ;
	}
	mij=(st+dr)/2;
	if(qpoz<=mij)
		update(nod*2,st,mij,paths,qpoz,y);
	else update(nod*2+1,mij+1,dr,paths,qpoz,y);
	arb[paths][nod]=max(arb[paths][nod*2],arb[paths][nod*2+1]);
}
void query(int nod, int st, int dr, int paths, int aa, int b)
{
	int mij;
	if((aa<=st)&&(dr<=b)) {
		if(arb[paths][nod]>valmax)
			valmax=arb[paths][nod];
		return ;
	}
	mij=(st+dr)/2;
	if(aa<=mij)
		query(nod*2,st,mij,paths,aa,b);
	if(mij<b)
		query(nod*2+1,mij+1,dr,paths,aa,b);
}
int maxim(int x, int y)
{
	int ret;
	ret=val[x];
	while(x!=y) {
		if(niv[x]>niv[y])
			swap(x,y);
		if(lant[x]==lant[y]) {
			valmax=-1;
			query(1,1,path[lant[y]].size()-1,lant[y],poz[x],poz[y]);
			ret=max(ret,valmax);
			y=x;
		}
		else {
			valmax=-1;
			query(1,1,path[lant[y]].size()-1,lant[y],1,poz[y]);
			ret=max(ret,valmax);
			y=up[path[lant[y]][1]];
		}
	}
	return ret;
}
void compute_rmq(int n)
{
	int i,j;
	for(i=2;i<=n;i++)
		lg[i]=lg[i/2]+1;
	for(i=1;i<=n;i++)
		a[0][i]=i;
	for(i=1;(1<<i)<=n;i++)
		for(j=1;j<=n-(1<<i)+1;j++) {
			a[i][j]=a[i-1][j];
			if(niv2[a[i][j]]>niv2[a[i-1][j+(1<<(i-1))]])
				a[i][j]=a[i-1][j+(1<<(i-1))];
		}
}
int lca(int i, int j)
{
	int l;
	if(i>j)
		swap(i,j);
	l=lg[j-i+1];
	if(niv2[a[l][i]]<niv2[a[l][j-(1<<l)+1]])
		return a[l][i];
	else return a[l][j-(1<<l)+1];
}
int main ()
{
	int n,m,i,x,y,tip;
	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].pb(y);
		v[y].pb(x);
	}
	dfs(1,0,1);
	for(i=1;i<=paths;i++) {
		reverse(path[i].begin()+1,path[i].end());
		for(vector <int> :: iterator it=path[i].begin()+1;it!=path[i].end();it++)
			poz[*it]=path[i].size()-poz[*it];
		arb[i].resize(4*(path[i].size()+1));
		init(1,1,path[i].size()-1,i);
	}
	compute_rmq(k);
	for(i=1;i<=m;i++) {
		f>>tip>>x>>y;
		if(tip==0) {
			val[x]=y;
			update(1,1,path[lant[x]].size()-1,lant[x],poz[x],y);
		}
		else g<<max(maxim(p[lca(poz2[x],poz2[y])],x),maxim(p[lca(poz2[x],poz2[y])],y))<<'\n';
	}
	f.close();
	g.close();
	return 0;
}