Cod sursa(job #931739)

Utilizator taigi100Cazacu Robert taigi100 Data 28 martie 2013 14:31:33
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.14 kb
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<utility>

using namespace std;

#define maxq 100010
#define max(a,b) ((a)>(b) ? (a):(b))

int n,m,v[maxq],fol[maxq],niv[maxq],w[maxq],lD[maxq],l[maxq],nl,lDad[maxq],lNiv[maxq],lPoz[maxq];
int arb[4*maxq];
vector<int> G[maxq],P[maxq];

pair<int, pair<int,int> > Op[maxq];
void read()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&v[i]);
	int x,y;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		G[x].push_back(y);
		G[y].push_back(x);
	}

	int a;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a,&x,&y);
		Op[i]=make_pair(a,make_pair(x,y));
	}
}

void df(int node)
{
	fol[node]=1;
	w[node]=1;
	
	int a=-1,frunza=1;

	for(vector<int>::iterator it=G[node].begin();it!=G[node].end();++it)
	{
		if(fol[*it])
			continue;

		frunza=0;
		niv[*it]=niv[node]+1;

		df(*it);

		w[node]+=w[*it];

		if(a==-1)
			a=*it;
		else
			if(w[a]<w[*it])
				a=*it;
	}
	if(frunza)
	{
		l[node] = ++nl;
		lD[nl]=1;
		P[nl].push_back(node);
		return;
	}
	l[node]=l[a];
	++lD[l[node]];
	P[l[node]].push_back(node);

	for(vector<int>::iterator it=G[node].begin();it!=G[node].end();it++)
	{
		if((*it)==a || niv[*it] < niv[node] )
			continue;
		lDad[l[*it]]=node;
		lNiv[l[*it]]=niv[node];
	}
}

void build(int node,int left,int right, int dec, int chain)
{
	if(left==right)
	{
		arb[node+dec]=v[P[chain][left-1]];
		return;
	}

	int mid=(left+right)/2;

	build(node*2,left,mid,dec,chain);
	build(node*2+1,mid+1,right,dec,chain);

	arb[node+dec]=max(arb[node*2+dec],arb[node*2+1+dec]);
}
void make_paths()
{
	niv[1]=1;
	df(1);

	for(int i=1;i<=nl;i++)
	{
		reverse(P[i].begin(),P[i].end());
		if(i>1)
			lPoz[i]= lPoz[i-1]+lD[i-1]*4;
		build(1,1,lD[i],lPoz[i],i);
	}
}

void update(int node,int left,int right,int pos,int val,int dec)
{
	if(left==right)
	{
		arb[node+dec]=val;
		return;
	}

	int mid=(left+right)/2;
	if(pos<=mid)
		update(node*2,left,mid,pos,val,dec);
	else
		update(node*2+1,mid+1,right,pos,val,dec);
	arb[node+dec]=max(arb[node*2+dec],arb[node*2+1+dec]);
}

int query(int node,int left,int right,int ql,int qr,int dec)
{
	if(ql<=left && right<=qr)
		return arb[node+dec];
	int mid=(left+right)/2,res=0;
	if(ql<=mid)
		res=max(res,query(node*2,left,mid,ql,qr,dec));
	if(mid<qr)
		res=max(res,query(node*2+1,mid+1,right,ql,qr,dec));
	return res;
}

void solve()
{
	int t,x,y,sol=0;

	for(int i=1;i<=m;i++)
	{
		t = Op[i].first; x = Op[i].second.first, y = Op[i].second.second;
		if(t==0)
			update(1,1,lD[l[x]],niv[x]-lNiv[l[x]],y,lPoz[l[x]]);
		else
		{
			sol=0;
			while(1)
			{
				if(l[x]==l[y])
				{
					if(niv[x]==niv[y])
						swap(x,y);
					sol=max(sol,query(1,1,lD[l[x]],niv[x]-lNiv[l[x]],niv[y]-lNiv[l[y]],lPoz[l[x]]));
					break;
				}
				if(lNiv[l[x]] < lNiv[l[y]] )
					swap(x,y);
				sol=max(sol,query(1,1,lD[l[x]],1,niv[x]-lNiv[l[x]],lPoz[l[x]]));
				x=lDad[l[x]];
			}
			printf("%d\n",sol);
		}
	}
}
int main()
{
	freopen("heavypath.in","r",stdin);
	freopen("heavypath.out","w",stdout);

	read();
	make_paths();
	solve();


	return 0;
}