Cod sursa(job #1022017)

Utilizator raulstoinStoin Raul raulstoin Data 4 noiembrie 2013 16:51:09
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.42 kb
#include<fstream>
#include<vector>

#define NMAX 100005
#define VEC p->val
#define son (nod<<1)
#define middle ((left+right)>>1)

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

struct Nod
{
	Nod *prev;
	int val;
}*G[NMAX],*split[NMAX];

vector<int> str[17],size;
int level[NMAX],what[NMAX],lant[NMAX],under[NMAX],vect[NMAX];
int *AINT,Maxx,K,L,R,poz,val;
int n,Q,v[NMAX],k,TT[NMAX];

void add(Nod *&x,int val)
{
	Nod *p=new Nod;
	p->val=val;
	p->prev=x;
	x=p;
}

void clear(Nod *&x)
{
	if(!x)
		return;
	for(Nod *p;x;x=p)
	{
		p=x->prev;
		delete x;
	}
}

void read()
{
	size.resize(NMAX,0);
	fin>>n>>Q;
	for(int i=1;i<=n;i++)
		fin>>v[i];
	for(int i=1,x,y;i<n;i++)
	{
		fin>>x>>y;
		size[x]++;
		size[y]++;
		add(G[x],y);
		add(G[y],x);
	}
}

inline void DFS(int nod,int tt)
{
	int maxim=-1;
	str[0][nod]=tt;
	level[nod]=level[tt]+1;
	if(size[nod]==1 && nod!=1)
	{
		lant[nod]=++k;
		add(split[k],nod);
		return;
	}
	for(Nod *p=G[nod];p;p=p->prev)
		if(VEC!=tt)
		{
			DFS(VEC,nod);
			under[nod]+=under[VEC]+1;
			if(maxim<under[VEC])
			{
				maxim=under[VEC];
				lant[nod]=lant[VEC];
			}
		}
	add(split[lant[nod]],nod);
}

void update(int left,int right,int nod)
{
	nod=vect[poz];
	AINT[nod]=val;
	for(nod>>=1;nod;nod>>=1)
		AINT[nod]=max(AINT[son],AINT[son+1]);   
}

void build_AINT(int left,int right,int nod)
{
	if(left==right)
	{
		AINT[nod]=vect[left];
		vect[left]=nod;
		return;
	}
	build_AINT(left,middle,son);
	build_AINT(middle+1,right,son+1);
	AINT[nod]=max(AINT[son],AINT[son+1]);
}

inline void query(int left,int right,int nod)
{
	if(left>R || right<L)
		return;
	if(L<=left && right<=R)
	{
		Maxx=max(Maxx,AINT[nod]);
		return;
	}
	query(left,middle,son);
	query(middle+1,right,son+1);
}

void group_init()
{
	for(int i=1,L=1;i<=k;i++)
	{
		TT[i]=split[i]->val;
		for(Nod *p=split[i];p;p=p->prev,L++)
		{
			what[ p->val ]=L;
			vect[L]=v[p->val];
		}
		clear(split[i]);
	}
	AINT=new int[(1<<18)];
	build_AINT(1,n,1);
}

void ancestors()
{
	for(int i=1;i<17;i++)
		str[i].resize(NMAX,0);
	for(int i=1;(1<<i)<=n;i++)
		for(int j=1;j<=n;j++)
			str[i][j]=str[i-1][str[i-1][j]];
}

void prep()
{
	str[0].resize(NMAX,0);
	DFS(1,0);
	for(int i=1;i<=n;i++)
		clear(G[i]);
	size.clear();
	group_init();
	ancestors();
}

void jump(int &x,int y)
{
	int d=level[x]-level[y];
	for(int step=16,p=(1<<16);step>=0;step--,p>>=1)
		if(d>=p)
		{
			d-=p;
			x=str[step][x];
		}
}

int LCA(int x,int y)
{
	if(level[x]>level[y])
		jump(x,y);
	if(level[x]<level[y])
		jump(y,x);
	if(x==y)
		return x;
	for(int step=16;step>=0;step--)
		if(str[step][x]!=str[step][y])
		{
			x=str[step][x];
			y=str[step][y];
		}
	return str[0][x];
}

void Val(int x,int lca,int &sol)
{
	while(level[x]>level[lca])
	{
		Maxx=0;
		R=what[x];
		if(lant[x]==lant[lca])
			L=what[lca];
		else
			L=what[TT[lant[x]]];
		query(1,n,1);
		sol=max(sol,Maxx);
		x=str[0][TT[lant[x]]];
	}
	sol=max(sol,v[lca]);
}

int main()
{
	read();
	prep();
	for(int op,x,y,lca,sol;Q;Q--)
	{
		fin>>op>>x>>y;
		if(!op)
		{
			val=v[x]=y;
			poz=what[x];
			update(1,n,1);
			continue;
		}
		sol=0;
		if(lant[x]!=lant[y])
			lca=LCA(x,y);
		else
			if(level[x]>level[y])
				lca=y;
			else
				lca=x;
		Val(x,lca,sol);
		Val(y,lca,sol);
		fout<<sol<<'\n';
	}
	
	return 0;
}