Cod sursa(job #662360)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 16 ianuarie 2012 16:31:28
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.39 kb
#include<stdio.h>
#include<vector>
#include<algorithm>

#define maxn 100005
#define pb push_back

using namespace std;

FILE*f=fopen("heavypath.in","r");
FILE*g=fopen("heavypath.out","w");

int n,m,i,x,y,paths,tip,poz_upd,val,a,b;
int v[maxn],Niv[maxn],subarb[maxn],lant[maxn],poz[maxn],up[maxn];
vector<int>G[maxn],P[maxn],Arb[maxn];

inline void citire () {
	
	fscanf(f,"%d %d",&n,&m);
	
	for ( i = 1 ; i <= n ; ++i ){
		fscanf(f,"%d",&v[i]);
	}
	
	for ( i = 1 ; i < n ; ++i ){
		fscanf(f,"%d %d",&x,&y);
		G[x].pb(y);
		G[y].pb(x);
	}
}

void dfs ( int nod , int niv , int t ){
	Niv[nod] = niv; subarb[nod] = 1;
	
	for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
		int nodvcn = (*itt);
		
		if ( nodvcn != t ){
			
			up[nodvcn] = nod;
			dfs(nodvcn,niv+1,nod);
			subarb[nod] += subarb[nodvcn];
		}
	}
	
	if ( G[nod].size() == 1 && nod != 1 ){
		
		lant[nod] = ++paths; P[ paths ].pb(0);
		P[ paths ].pb(nod); poz[nod] = 1;
		
		return ;
	}
	
	int hv = 0;
	for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
		int nodvcn = (*itt);
		
		if ( nodvcn != t ){
			if ( subarb[nodvcn] > subarb[hv] ){
				hv = nodvcn;
			}
		}
	}
	
	lant[nod] = lant[hv];
	P[ lant[nod] ].pb(nod); poz[nod] = P[ lant[nod] ].size() - 1;
}

void init ( int nod , int st , int dr , int ind ){
	
	if ( st == dr ){
		Arb[ind][nod] = v[ P[ind][st] ];
		return ;
	}
	
	int mij = (st + dr) >> 1;
	int nodst = nod << 1;
	int noddr = nodst + 1;
	
	init(nodst,st,mij,ind);
	init(noddr,mij+1,dr,ind);
	
	Arb[ind][nod] = max(Arb[ind][nodst],Arb[ind][noddr]);
}

void update ( int nod , int st , int dr , int ind ){
	
	if ( st == dr ){
		Arb[ind][nod] = val;
		return ;
	}
	
	int mij = (st + dr) >> 1;
	int nodst = nod << 1;
	int noddr = nodst + 1;
	
	if ( poz_upd <= mij ){
		update(nodst,st,mij,ind);
	}
	else{
		update(noddr,mij+1,dr,ind);
	}
	
	Arb[ind][nod] = max(Arb[ind][nodst],Arb[ind][noddr]);
}

void query ( int nod , int st , int dr , int ind , int &sol ){
	
	if ( a <= st && dr <= b ){
		sol = max(sol,Arb[ind][nod]);
		return ;
	}
	
	int mij = (st + dr) >> 1;
	int nodst = nod << 1;
	int noddr = nodst + 1;
	
	if ( a <= mij ){
		query(nodst,st,mij,ind,sol);
	}
	if ( b > mij ){
		query(noddr,mij+1,dr,ind,sol);
	}
}

inline int find_max ( int x , int y ){
	int sol = 0;
	
	for ( ; ; ){
		
		if ( lant[x] == lant[y] ){
			int u = lant[x];
			
			a = min(poz[x],poz[y]); b = max(poz[x],poz[y]);
			query(1,1,P[u].size()-1,u,sol);
			
			break ;
		}
		
		int t1 = P[lant[x]][1];
		int t2 = P[lant[y]][1];
		
		if ( Niv[t1] < Niv[t2] ){
			swap(x,y);
		}
		
		a = 1; b = poz[x]; query(1,1,P[lant[x]].size()-1,lant[x],sol);
		x = up[ P[lant[x]][1] ];
	}
	
	return sol;
}

inline void solve () {
	
	dfs(1,1,0);
	
	for ( int i = 1 ; i <= paths ; ++i ){
		reverse(P[i].begin()+1,P[i].end());
		Arb[i].resize(4*(P[i].size()+1));
		init(1,1,P[i].size()-1,i);
	}
	
	for ( int i = 1 ; i <= n ; ++i ){
		poz[i] = P[lant[i]].size() - poz[i];
	}
	
	for ( int i = 1 ; i <= m ; ++i ){
		fscanf(f,"%d %d %d",&tip,&x,&y);
		
		if ( !tip ){
			poz_upd = poz[x]; val = y;
			update(1,1,P[ lant[x] ].size()-1,lant[x]);
		}
		else{
			fprintf(g,"%d\n",find_max(x,y));
		}
	}
}

int main () {
	
	citire();
	
	solve();	
	
	fclose(f);
	fclose(g);
	
	return 0;
}