Cod sursa(job #634464)

Utilizator katakunaCazacu Alexandru katakuna Data 16 noiembrie 2011 14:28:40
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.6 kb
// cod naspa. treb sa i-o dau lu jean
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;

#define Nmax 200010

int n, m;
int viz[Nmax], Nr[Nmax], Val[Nmax];
vector <int> V[Nmax];
vector <int> AI[Nmax];

int Cate[Nmax], Lant[Nmax], Poz[Nmax], Leg[Nmax], Tata[Nmax], Tlant[Nmax], Niv[Nmax], Bla[Nmax]; 

int Lca (int x, int y) {

	while ( Lant[x] != Lant[y] ) {
		if ( Niv[ Tlant[ Lant[x] ] ] > Niv[ Tlant[ Lant[y] ] ] ) x = Leg[ Lant[x] ];     
		else y = Leg[ Lant[y] ]; 
	}

	if (Niv[x] < Niv[y]) return x;
	return y;
}

int VAL, POZ, A, B, REZ;
#define MIJ ((st + dr) >> 1)
#define N1 (nod << 1)
#define N2 ((nod << 1) + 1)

void updateAi (int lant, int nod, int st, int dr) {
	
	if (st == dr) {	
		AI[lant][nod] = VAL;  
		return ;
	} 

	if (POZ <= MIJ) updateAi (lant, N1, st, MIJ);
	else updateAi (lant, N2, MIJ + 1, dr);

	AI[lant][nod] = max ( AI[lant][N1], AI[lant][N2] );
}

void queryAi (int lant, int nod, int st, int dr) {
	
	if (st == dr) {
		REZ = max (REZ, AI[lant][nod]);		
		return ;
	}

	if (A <= MIJ) queryAi (lant, N1, st, MIJ);
	if (MIJ < B) queryAi (lant, N2, MIJ + 1, dr);
}

void query (int x, int y) {
	
	int aux;
	if (Niv[x] < Niv[y]) {
		aux = x;
		x = y;
		y = aux;
	}

	//printf ("-------\n");
	for (;Lant[x] != Lant[y]; x = Leg[ Lant[x] ]) {
		//printf ("%d %d\n", x ,y);
		A = 1;
		B = Poz[ x ];            
		if (A > B) {
			aux = A;
			A = B;
			B = aux;
		}
		//printf ("%d %d %d\n", Lant[x], A, B);
		queryAi (Lant[x], 1, 1, Cate[ Lant[x] ]);   	
	}

	//printf ("%d %d\n", x, y);

    A = Poz[x];
	B = Poz[y];	
	if (A > B) {		
		aux = A; 
		A = B;
		B = aux;
	} 

	//printf ("%d %d %d\n", Lant[x], A, B); 
	queryAi (Lant[x], 1, 1, Cate[ Lant[x] ]);
	//printf ("-------\n");
}

void heavypath (int nod, int lant) {

	viz[nod] = 1;
	Lant[nod] = lant; Poz[nod] = ++Cate[lant];
                       
	if (Poz[nod] == 1) Tlant[lant] = nod;

	for (vector <int>::iterator it = V[nod].begin (); it != V[nod].end (); it++)
		if (viz[*it] == 0) {
			if (Bla[nod] == 0) Bla[nod] = 1, heavypath (*it, lant);
			else {
				Cate[0]++;
				Leg[ Cate[0] ] = nod;
				heavypath (*it, Cate[0]);
			}
		}  
}   
	
void dfs (int nod, int niv) {
	
	viz[nod] = 1; Nr[nod] = 1; Niv[nod] = niv;
	for (vector <int>::iterator it = V[nod].begin (); it != V[nod].end (); it++)
		if (viz[*it] == 0) {
			dfs (*it, niv + 1);
			Nr[nod]+= Nr[*it];
			Tata[*it] = nod;
		}
}

void readData () {
	
	int i, x, y;

	scanf ("%d %d", &n, &m);
	for (i = 1; i <= n; i++)
		scanf ("%d", &Val[i]);

	for (i = 1; i < n; i++) {
		scanf ("%d %d", &x, &y);
		V[x].push_back (y);
		V[y].push_back (x);
	}
}

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

int main () {

	freopen ("heavypath.in", "r", stdin);
	freopen ("heavypath.out", "w", stdout);

	readData ();
	dfs (1, 1);	
                                                                                    
	int i, j;
	memset (viz, 0, sizeof (viz));
	for (i = 1; i <= n; i++)
		sort (V[i].begin (), V[i].end (), cmp);

	Cate[0] = 1;
	heavypath (1, 1);

	int len;
	for (i = 1; i <= Cate[0]; i++) {
		len = 4 * Cate[i];
		for (j = 1; j <= len; j++)
			AI[i].push_back (0);
	} 

	for (i = 1; i <= n; i++) {
		POZ = Poz[i];
		VAL = Val[i];

		updateAi (Lant[i], 1, 1, Cate[ Lant[i] ]);
	}

	int tip, x, y, lca;
	for (i = 1; i <= m; i++) {
		scanf ("%d", &tip);
		if (tip == 0) {
			scanf ("%d %d", &x, &y);
			POZ = Poz[x];
			VAL = y;

			updateAi (Lant[x], 1, 1, Cate[ Lant[x] ]);
		}
		else {
			scanf ("%d %d", &x, &y);
			lca = Lca (x, y);

			//printf ("%d %d %d\n", x, y, lca);

			REZ = 0;
			query (x, lca);
			query (y, lca);
			
			printf ("%d\n", REZ);
		}
	} 

	return 0;
}