Cod sursa(job #1021318)

Utilizator raulstoinStoin Raul raulstoin Data 3 noiembrie 2013 17:40:16
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.13 kb
#include<fstream>
#include<vector>
#include<algorithm>

#define NMAX 100005
#define VEC G[nod][i]
#define son (nod<<1)
#define middle ((left+right)>>1)

using namespace std;

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

vector<int> G[NMAX];
int level[NMAX],str[17][NMAX],what[NMAX],lant[NMAX],under[NMAX];
int AINT[(1<<18)],Maxx,start[NMAX],K;
int n,Q,v[NMAX],k,TT[NMAX];

void read()
{
	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;
		G[x].push_back(y);
		G[y].push_back(x);
	}
}

void DFS(int nod,int tt)
{
	str[0][nod]=tt;
	level[nod]=level[tt]+1;
	for(size_t i=0;i<G[nod].size();i++)
		if(VEC!=tt)
		{
			DFS(VEC,nod);
			under[nod]+=under[VEC]+1;
		}
	if(G[nod].size()==1 && nod!=1)
	{
		lant[nod]=++k;
		return;
	}
	int ind=0,maxim=-1;
	for(size_t i=0;i<G[nod].size();i++)
		if(VEC!=tt && maxim<under[VEC])
		{
			maxim=under[VEC];
			ind=VEC;
		}
	lant[nod]=lant[ind];
}

inline void update(int left,int right,int nod,int val,int poz)
{
    if(left==right)
    {
        AINT[nod]=val;
        return;
    }
    if(poz<=middle)
        update(left,middle,son,val,poz);
    else
        update(middle+1,right,son+1,val,poz);
    AINT[nod]=max(AINT[son],AINT[son+1]);
}

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

bool cmp(const int a,const int b)
{
	if(lant[a]==lant[b])
		return level[a]<level[b];
	return lant[a]<lant[b];
}

void group_init()
{
	int nods[NMAX];
	for(int i=1;i<=n;i++)
		nods[i]=i;
	sort(nods+1,nods+n+1,cmp);
	for(int i=1,L=1,ant=0;i<=n;i++,L++)
	{
		if(lant[nods[i]]!=ant)
		{
			ant=lant[ nods[i] ];
			start[ lant[ nods[i] ] ]=L;
			TT[ lant[ nods[i] ] ]=nods[i];
		}
		what[nods[i]]=L;
		update(1,n,1,v[nods[i]],L);
	}
}

void ancestors()
{
	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()
{
	DFS(1,0);
	group_init();
	ancestors();
}

void jump(int &x,int &y)
{
	int d=level[x]-level[y];
	for(int step=17,p=(1<<17);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=17;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(x!=lca)
	{
		Maxx=0;
		if(lant[x]==lant[lca])
		{
			query(1,n,1,what[lca],what[x]);
			sol=max(sol,Maxx);
			break;
		}
		query(1,n,1,start[lant[x]],what[x]);
		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)
		{
			v[x]=y;
			if(lant[x])
				update(1,n,1,y,what[x]);
			continue;
		}
		sol=0;
		lca=LCA(x,y);
		val(x,lca,sol);
		val(y,lca,sol);
		fout<<sol<<'\n';
	}
	
	return 0;
}