Cod sursa(job #644694)

Utilizator Bogdan_tmmTirca Bogdan Bogdan_tmm Data 7 decembrie 2011 15:00:10
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.22 kb
#include <algorithm>
#include <vector>
#include <stdio.h>

using namespace std;

#define N_MAX 100001
#define LEFT (nod << 1)
#define RIGHT ((nod << 1) | 1)

int cost[N_MAX], tata[N_MAX], fii[N_MAX];
int lungime[N_MAX], drumuri, poz[N_MAX], tataDrum[N_MAX];
bool ut[N_MAX];

vector <int> aint[N_MAX];

vector <int> graf[N_MAX];

int n, m, i, j, x, y, op;

//****//
//vector <int> d[N_MAX];
//***//

void heavypath(int nod){
	ut[nod] = 1;
	if(graf[nod].size() == 1 && nod != 1){
		fii[nod] = 1;
		drumuri ++;
		tata[nod] = drumuri;
		poz[nod] = ++ lungime[drumuri];
		return ;
	}
	int nodMax = 0;
	for(int i = 0; i < (int)graf[nod].size(); i ++){
		if(ut[graf[nod][i]])
			continue;
		heavypath(graf[nod][i]);
		fii[nod] += fii[graf[nod][i]];
		if(fii[graf[nod][i]] > fii[nodMax])
			nodMax = graf[nod][i];
	}
	for(int i = 0; i < (int)graf[nod].size(); i ++){
		if(graf[nod][i] != nodMax)
			tataDrum[tata[graf[nod][i]]] = nod;
	}
	tata[nod] = tata[nodMax];
	poz[nod] = ++ lungime[tata[nod]];
}

int INDEX, POZ, VAL, ST, DR;

void update(int nod, int st, int dr){
	if(st == dr){
		aint[INDEX][nod] = VAL;
		return ;
	}
	int mid = (st + dr) >> 1;
	if(POZ <= mid)
		update(LEFT, st, mid);
	if(POZ > mid)
		update(RIGHT, mid + 1, dr);
	aint[INDEX][nod] = max(aint[INDEX][LEFT], aint[INDEX][RIGHT]);
}

int query(int nod, int st, int dr){
	if(ST <= st && dr <= DR)
		return aint[INDEX][nod];
	
	int mid = (st + dr) >> 1;
	int rez = 0;
	
	if(ST <= mid)
		rez = max(rez, query(LEFT, st, mid));
	if(mid < DR)
		rez = max(rez, query(RIGHT, mid + 1, dr));
	
	return rez;
}

int lca(int x, int y){
	int Max = 0;
	while(tata[x] != tata[y])
		if(tata[x] > tata[y]){
			INDEX = tata[x];	ST = 1;	DR = poz[x];
			Max = max(Max, query(1, 1, lungime[tata[x]]));
			x = tataDrum[tata[x]];
		}
		else{
			INDEX = tata[y];	ST = 1;	DR = poz[y];
			Max = max(Max, query(1, 1, lungime[tata[y]]));
			y = tataDrum[tata[y]];
		}
	INDEX = tata[x];	ST = min(poz[x], poz[y]);	DR = max(poz[x], poz[y]);
	Max = max(Max, query(1, 1, lungime[tata[x]]));
	
	return Max;
}

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", &cost[i]);
	
	for(i = 1; i < n; i ++){
		scanf("%d %d", &x, &y);
		graf[x].push_back(y);
		graf[y].push_back(x);
	}
	
	heavypath(1);
	
	for(i = 1; i <= drumuri; i ++)
		aint[i].resize(4 * lungime[i] + 10);
	
	for(i = 1; i <= n; i ++){
		poz[i] = lungime[tata[i]] + 1 - poz[i];
		
		INDEX = tata[i];	POZ = poz[i];	VAL = cost[i];
		update(1, 1, lungime[tata[i]]);
	}

	//Opearatii
	for(i = 1; i <= m; i ++){
		scanf("%d %d %d", &op, &x, &y);
		if(op == 0){
			INDEX = tata[x];	POZ = poz[x];	VAL = y;
			update(1, 1, lungime[tata[x]]);
		}
		else{
			printf("%d\n",lca(x, y));
		}
	}
	
	/*********************
	for(i = 1; i <= n; i ++){
		if(d[tata[i]].empty())
			d[tata[i]].resize(lungime[tata[i]] + 1);
		d[tata[i]][poz[i]] = i;
	}
	
	
	for(i = 1; i <= drumuri; i ++){
		for(j = 1; j < d[i].size(); j ++)
			printf("%d ", d[i][j]);
		printf(" -> %d", tata[d[i][1]]);
		printf(" | tataDrum -> %d", tataDrum[i]);
		printf("\n");
	}
	*/
	return 0;
}