Cod sursa(job #854192)

Utilizator Luncasu_VictorVictor Luncasu Luncasu_Victor Data 12 ianuarie 2013 21:43:23
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.84 kb
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <ctime>
#include <cassert>
using namespace std;

#define PRO "heavypath"
void OpenFiles(int EVAL)
{
	if(EVAL)
	{
		char input[100] = PRO, output[100] = PRO;
		freopen(strcat(input, ".in"),"r",stdin);
		freopen(strcat(output,".out"),"w",stdout);
	} else
	{
		freopen("test.in","r",stdin);
		freopen("test.out","w",stdout);
	}
}

#define MAX 100001
#define MOD 666013
#define INF 0xffffff
#define EPS 1E-8

vector<int>graf[MAX], path[MAX], inter[MAX];
int val_nod[MAX], nr_sub[MAX], nr_niv[MAX], parent[MAX], whatpath[MAX], whatpos[MAX];
bool nod_vizitat[MAX];
int n, nr_path, retq;

void dfs_sub(int x,int cur_niv)
{
	nr_niv[x] = cur_niv;
	nod_vizitat[x] = 1;
	for(int i=0;i<graf[x].size();i++)
	if(!nod_vizitat[ graf[x][i] ])
	{
		dfs_sub( graf[x][i], cur_niv + 1 );
		nr_sub[x] += nr_sub[ graf[x][i] ];
	}
	nr_sub[x] += 1;
}

void dfs_lant(int x,int nr_path,int pos)
{
	//printf("(%d %d %d) ,",x,nr_path,pos);
	nod_vizitat[x] = 1;
	whatpath[x] = nr_path;
	whatpos[x] = pos;
	path[ nr_path ].push_back( x );
	int next = 0;
	for(int i=0;i<graf[x].size();i++)
	if(!nod_vizitat[ graf[x][i] ] && (next == 0 || nr_sub[ graf[x][i] ] > nr_sub[ next ])) next = graf[x][i];
	if(next && !nod_vizitat[ next ])
	{
		parent[ next ] = x;
		dfs_lant( next, nr_path, pos+1);
		return;
	}
}

int lca(int x,int y)
{
	if(x == y)return x;
	else
	{
		if( nr_niv[x] > nr_niv[y] )
			lca(parent[x],y); else
			lca(x,parent[y]);
	}
}

void update(vector<int>&path,int pos,int val,int nod,int lf,int rt)
{
	//printf("%d %d %d %d %d\n",pos,val,nod,lf,rt);
	if(lf == rt)
	{
		path[nod] = val;
		return;
	}
		int md = (lf+rt)/2;
		if(pos <= md) update(path,pos,val,2*nod,lf,md); else
					update(path,pos,val,2*nod+1,md+1,rt);
		path[nod] = max( path[2*nod], path[2*nod+1] );
}

void query(vector<int>path, int st, int dr, int nod, int lf, int rt)
{
	if(st <= lf && rt <= dr)
	{
		retq = max( retq, path[nod] );
		return;
	}
		int md = (lf+rt)/2;
		if(st <= md) query(path, st, dr, 2*nod, lf, md);
			if( dr > md ) query(path, st, dr, 2*nod+1, md+1, rt);
}

int heavy_query(int x,int y)
{
	int ret = val_nod[ x ];
	while( x != y )
	{
		if( whatpath[ x ] == whatpath[ y ] )
		{
			retq = 0;
			query(inter[ whatpath[x] ], whatpos[x], whatpos[y], 1, 1, path[ whatpath[x] ].size()-1);
			ret = max( ret, retq );
			y = x;
		} else
		{
			retq = 0;
			query(inter[ whatpath[y] ], 1, whatpos[y], 1, 1, path[ whatpath[y] ].size()-1);
			ret = max( ret, retq );
			y = parent[y];
		}
	}
	return ret;
}

int main(int argv,char *args[])
{	
OpenFiles(argv==0);
	/* start code */
	int m,t,x,y;
		scanf("%d %d",&n,&m);	
		for(int i=1;i<=n;i++) scanf("%d",&val_nod[i]);
		for(int i=1;i<n;i++)
		{
			scanf("%d %d",&x,&y);
			graf[x].push_back(y);
			graf[y].push_back(x);
		}
		dfs_sub(1,1);
		//for(int i=1;i<=n;i++)printf("%d ",nr_sub[i]); printf("\n");
		//for(int i=1;i<=n;i++)printf("%d ",nr_niv[i]); printf("\n");
		memset(nod_vizitat,0,sizeof(nod_vizitat));
		for(int i=1;i<=n;i++)
		if(!nod_vizitat[i])
		{
			for(int j=0;j<graf[i].size();j++)
				if(nod_vizitat[ graf[i][j] ])
				{
					parent[i] = graf[i][j];
					break;
				}
			nr_path += 1;
			path[ nr_path ].push_back(0);
			dfs_lant(i, nr_path, 1);
			//printf("\n");
		}
		//for(int i=0;i<path[1].size();i++)printf("%d ",path[1][i]); return 0;
		//inter[1].resize(1<<int(log( double(path[1].size()) )/log( double(2) ) + 1));
		for(int nr_i = 1; nr_i <= nr_path; nr_i++)
		{
			inter[ nr_i ].resize(1<<int(log( double(path[ nr_i ].size()) )/log( double(2) ) + 1));
			for(int i=1;i<path[ nr_i ].size();i++)
			{//printf("------------\n");
			update( inter[nr_i], i, val_nod[ path[ nr_i ][i] ], 1, 1, path[ nr_i ].size()-1);}
			//for(int i=1;i<inter[ nr_i ].size();i++ )printf("%d ",inter[ nr_i ][i]);
			//printf("\n");
		}
		
		/*int str; x = 1; y = 6;
		str = lca( x, y );
				printf("%d\n",max( heavy_query(str, x), heavy_query(str, y) ));
		*/
		int str;
		while(m--)
		{
			scanf("%d %d %d",&t ,&x, &y);
			if(t)
			{
			if(x == 1 && y == 6)
				str=0;
				if(x>y)swap( x, y );
				str = lca( x, y );
				printf("%d\n",max( heavy_query(str, x), heavy_query(str, y) ));
			} else
			{
				val_nod [x] = y;
				//printf("(%d) ",whatpath[x]);s
				update( inter[ whatpath[x] ], whatpos[x], y, 1, 1, path[ whatpath[x] ].size() - 1);
				//for(int i=1;i<inter[ whatpath[x] ].size();i++)printf("%d ",inter [ whatpath[x] ][i]); printf("\n");
			}
		}

		//for(int i=1;i<=n;i++)
		//	for(int j=1;j<=n;j++)
		//		if(whatpath[i] != whatpath[j]) printf("lca(%d,%d)=%d\n",i,j,lca(i,j));
	/* end */
	return 0;
}