Cod sursa(job #658511)

Utilizator jeanFMI - Petcu Ion Cristian jean Data 8 ianuarie 2012 23:02:30
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.3 kb
#include<stdio.h>
#include<vector>
#include<algorithm>
#define Nmax 100010
#define st nod<<1 
#define dr 1 + (nod<<1)
#define mij ((s+d)>>1)
using namespace std ;

int T[Nmax],Lant[Nmax],Tata[Nmax],viz[Nmax],heavy[Nmax],Lungime[Nmax],key[Nmax],poz_in_lant[Nmax];
int a,b,x,y,new_val,ret_val,N,M,i,lanturi,op,poz;

vector<int> Arb[Nmax],AINT[Nmax];

int cmp ( int a, int b ) 
{
	return heavy[a] > heavy[b] ; 
}

void update ( int L, int nod, int s, int d ) 
{
	if ( s == d ) 
	{
		AINT[L][nod] = new_val ; 
		return ; 
	}
	
	if ( poz <= mij ) update( L , st, s, mij ) ;
	else			  update( L , dr, mij+1, d ) ; 
	
	AINT[L][nod] = AINT[L][st] ;
	if( key[ AINT[L][st] ] < key[ AINT[L][dr] ] )
		AINT[L][nod] = AINT[L][dr] ;
}

void query ( int L, int nod, int s, int d ) 
{
	if ( a <= s && d <= b ) 
	{
		if ( key[AINT[L][nod]] > ret_val )
			ret_val = key[AINT[L][nod]] ; 
		return ;
	}
	
	if ( a <= mij ) query ( L, st, s, mij ) ; 
	if ( mij < b  ) query ( L, dr, mij+1, d ) ;
}

void dfs ( int nod ) 
{
	int N = Arb[nod].size(), fiu ;
	
	viz[nod] = 1 ;
	
	for( int i = 0 ; i < N ; i++ ) 
	{
		fiu = Arb[nod][i] ;
		if( !viz[fiu] ) 
		{	Tata[fiu] = nod , dfs( fiu ) ;
		    heavy[nod] += heavy[ fiu ] ;
		}			
	}
	
	heavy[nod]++;
	sort(Arb[nod].begin(),Arb[nod].end(),cmp);
}

void decomp ( int nod, int poz ) 
{
	int N = Arb[nod].size(), fiu ; 
	
	if( !T[lanturi] ) T[lanturi] = nod ;
	
	Lant[nod] = lanturi ; 
	poz_in_lant[nod] = poz ;
	Lungime[lanturi] = poz ; 
	
	// taraneala
	AINT[lanturi].push_back(0) ; 
	AINT[lanturi].push_back(0) ; 
	AINT[lanturi].push_back(0) ; 
	AINT[lanturi].push_back(0) ; 
	
	int primul = 1 ;
	for ( int i = 0 ; i < N ; i++ )
	{
		fiu = Arb[nod][i] ;
		if( nod != Tata[fiu] ) continue ; 
		if ( !primul ) 
		{
			lanturi++;
			decomp( fiu , 1 ) ; 
			T[Lant[fiu]] = nod ; 
		}
		else
			primul = 0, decomp( fiu , poz + 1 ) ;
	}
}

int get_max ( int x, int y ) 
{
	int r = 0 ;
	
	while ( Lant[x] != Lant[y] ) 
	{
		ret_val = 0 ; a = 1 ; 
		if( Lant[x] < Lant[y] ) 
		{
			b = poz_in_lant[y];
			query(Lant[y],1,1,Lungime[Lant[y]]);
			if( ret_val > r ) 
				r = ret_val ; 
			y = T[Lant[y]];
		}
		else
		{
			b = poz_in_lant[x];
			query(Lant[x],1,1,Lungime[Lant[x]]);
			if( ret_val > r ) 
				r = ret_val ; 
			x = T[Lant[x]];
		}
	}
	
	a = poz_in_lant[x];
	b = poz_in_lant[y];
	if( a > b ) a = a+b - (b=a);
	
	ret_val = 0 ;
	query(Lant[x],1,1,Lungime[Lant[x]]);
	if( ret_val > r ) r = ret_val ; 
	
	return r ;
}

int main()
{
	freopen("heavypath.in","r",stdin);
	freopen("heavypath.out","w",stdout);
	
	scanf("%d %d",&N,&M);
	
	for( i = 1 ; i <= N ; i++ ) 
		scanf("%d",&key[i]);
	
	for( i = 1 ; i < N ; i++ )
	{
		scanf("%d %d",&a,&b);
		Arb[a].push_back(b);
		Arb[b].push_back(a);
	}
	
	Tata[1] = 1 ; 
	dfs(1); 
	lanturi = 1 ;
	decomp(1,1);
	
	for( i = 1 ; i <= N ; i++ )
	{
		new_val = i ; 
		poz = poz_in_lant[i];
		update(Lant[i],1,1,Lungime[Lant[i]]) ;
	}
	
	for( i = 1 ; i <= M ; i++ )
	{
		scanf("%d",&op);
		if( op )
		{
			scanf("%d %d",&x,&y);
			printf("%d\n",get_max(x,y));
		}
		else
		{
			scanf("%d %d",&x,&new_val);
			key[x] = new_val;
			new_val = x ; 
			poz = poz_in_lant[x];
			update(Lant[x],1,1,Lungime[Lant[x]]);
		}
	}
	
	return 0 ; 
}