Cod sursa(job #944277)

Utilizator roots4Irimia Alexandru Gabriel roots4 Data 27 aprilie 2013 22:25:22
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.24 kb
#include<fstream>
#include<vector>

using namespace std;

#define max_n 100010

ifstream f("heavypath.in");
ofstream g("heavypath.out");

vector<int> L[max_n];
vector<int> Lant[max_n];
struct aib{
	int max;
	aib *st , *dr;
}*A[1000];

int V[max_n] , CLant[max_n] , PLant[max_n] , S[max_n] , T[max_n] , Niv[max_n];
int op , x , y , v_max , k , n , m;
int D[max_n];

void read(){
	int a , b;
	f>>n>>m;
	
	for(register int i = 1 ; i <= n ; i++)
		f>>V[i];
	
	for(register int i = 1 ; i < n ; i++){
		f>>a>>b;
		L[a].push_back(b);
		L[b].push_back(a);
	}
	
}

void dfs(int nod , int niv , int tata){
	int nod2 , nod_max , maxim = -1;
	S[nod] = 1; Niv[nod] = niv; T[nod] = tata;
	
	for(unsigned int i = 0 ; i < L[nod].size() ; i++){
		nod2 = L[nod][i];
		if( nod2 == tata )
			continue;
		dfs(nod2 , niv + 1 , nod);
		S[nod] += S[nod2];
		if(S[nod2] > maxim) maxim = S[nod2] , nod_max = nod2;
	}
	
	if( L[nod].size() == 1 && nod != 1 ){
		Lant[++k].push_back(1);
		Lant[k].push_back(nod); D[k]++ ; CLant[nod] = k; PLant[nod] = D[k];
	}
	else{
		int lant = CLant[nod_max];
		Lant[lant].push_back(nod); D[lant]++; CLant[nod] = lant; PLant[nod] = D[lant];
	}
	
} 

inline int vMax(int a , int b){
	return a>b?a:b;
}

void create(aib *T , int st , int dr , int lant){
	if(st == dr)
		T->max = V[Lant[lant][st]];
	else{
		int mid = ((st + dr) >> 1);
		T->st = new aib;	T->dr = new aib;
		create(T->st , st , mid , lant);
		create(T->dr , mid+1 , dr , lant);
		T->max = vMax(T->st->max , T->dr->max);
	}
}

void form_aib(){
	
	for(int i = 1 ; i <= k ; i++){
		A[i] = new aib;
		create(A[i] , 1 , D[i] , i);
	}
	
}

void update(aib *T , int st , int dr , int poz){
	if(st == dr && st == poz)
		T->max = V[x];
	else{
		int mid = ((st + dr) >> 1);
		if(poz <= mid)
			update(T->st , st , mid , poz);
		else
			update(T->dr , mid + 1 , dr , poz);
		T->max = vMax(T->st->max , T->dr->max);
	}
}

bool intersectie(int st , int dr , int a , int b){
	if(a >= st && a <= dr) return 1;
	if(b >= st && b <= dr) return 1;
	if(st >= a && st <= b) return 1;
	if(dr >= a && dr <= b) return 1;
	return 0;
}

void querry(aib *T , int st , int dr , int a , int b){
	if(st >= a && dr <= b)
		v_max = vMax(v_max , T->max);
	else{
		int mid = ((st + dr) >> 1);
		if(intersectie(st , mid , a , b))
			querry(T->st , st , mid , a , b);
		if(intersectie(mid+1 , dr , a , b))
			querry(T->dr , mid+1 , dr , a , b);
	}
}

void solve(){
	
	while(m--){
		f>>op>>x>>y;
		switch(op){
		case 0:
			V[x] = y;
			update( A[CLant[x]] , 1 , D[CLant[x]] , PLant[x] );
			break;
		default:
			
			int l1 = CLant[x] , l2 = CLant[y] ; v_max = -1;
			
			while(l1 != l2){
				if(Niv[Lant[l1][D[l1]]] < Niv[Lant[l2][D[l2]]]){
					querry(A[l2] , 1 , D[l2] , PLant[y] , D[l2]);
					y = T[Lant[l2][D[l2]]];
				}
				else{
					querry(A[l1] , 1 , D[l1] , PLant[x] , D[l1]);
					x = T[Lant[l1][D[l1]]];
				}
				l1 = CLant[x] ; l2 = CLant[y];
			}
			
			int p1 = PLant[x] , p2 = PLant[y];
			if(p2 < p1)	swap(p1 , p2);
			
			querry(A[l1] , 1 , D[l1] , p1 , p2);
			
			g<<v_max<<"\n";
			
			break;
		}
	}
	
}

int main(){
	
	read();
	
	dfs(1 , 1 , 0);
	
	form_aib();
	
	solve();
	
	return 0;
}