Cod sursa(job #626493)

Utilizator cosmyoPaunel Cosmin cosmyo Data 27 octombrie 2011 12:26:46
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.72 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100005;
struct tip {
	vector<int> array;
	int parent, depth;
};

struct operatie{
	int t, x, y;
} op[N];

vector<tip> Paths;
vector< vector<int> > ARB_INT;
int  whatPath[N], whatPos[N];

vector<int> a[N];
int t[N], v[N], d[N], DEPTH[N], x[N], n, m;

inline int max(int a, int b) {
	return a < b ? b : a;
}

void dfs(int k) {
	int i, r = 0;
	v[k] = 1;
	for(i = 0; i < a[k].size(); ++i) 
		if(!v[a[k][i]]){
			t[a[k][i]] = k;
			DEPTH[a[k][i]] = DEPTH[k] + 1;
			dfs(a[k][i]);
			d[k] += d[a[k][i]];
			
			if(d[r] < d[a[k][i]])
				r = a[k][i];
		}

	if(r == 0){
		Paths.resize(Paths.size() + 1);
		Paths[Paths.size() - 1].array.push_back(k);
		Paths[Paths.size() - 1].parent = k;
		whatPath[k] = Paths.size() - 1;
	}

	else{
		Paths[whatPath[r]].array.push_back(k);
		Paths[whatPath[r]].parent = k;
		whatPath[k] = whatPath[r];
	}

}

void update(int val, int Path, int Pos, int st, int dr, int poz){
	if(st > Pos)
		return ;
	if(dr < Pos)
		return ;
	if(st == dr && Pos == st){
		ARB_INT[Path][poz] = val;
		return ;
	}
	
	int x = (st + dr) / 2;
	update(val, Path, Pos, st, x, poz * 2);
	update(val, Path, Pos, x + 1, dr, poz * 2 + 1);
	
	ARB_INT[Path][poz] = max(ARB_INT[Path][poz * 2], ARB_INT[Path][poz * 2 + 1]);
}

int query(int p1, int p2, int Path, int st, int dr, int poz){
	if(p1 > dr || p2 < st)
		return 0;
	if(p1 <= st && dr <= p2)
		return ARB_INT[Path][poz];
	
	int x = (st + dr) / 2;
	int q1 = query(p1, p2, Path, st, x, poz * 2);
	int q2 = query(p1, p2, Path, x + 1, dr, poz * 2 + 1);
	
	return max(q1, q2);
}

ofstream fout("heavypath.out");
void solve(int ind) {
	int i, j, sol = 0, x, y;
	if(op[ind].t == 0)
		update(op[ind].y, whatPath[op[ind].x], whatPos[op[ind].x], 0, Paths[whatPath[op[ind].x]].array.size() - 1 , 1);
else
	{

		x = op[ind].x;
		y = op[ind].y;
		int it = 0;
		while(x != y && it <= 10) {
			++it;
//			printf("%d %d %d %d\n", x, y, Paths[whatPath[x]].depth, Paths[whatPath[y]].depth);
			if(whatPath[x] == whatPath[y]){
				if(DEPTH[x] > DEPTH[y])
					swap(x, y);

				sol = max(sol, query(whatPos[x], whatPos[y], whatPath[x], 0, Paths[whatPath[x]].array.size() - 1, 1));
				x = y;
			}
			else{
			if(Paths[whatPath[x]].depth < Paths[whatPath[y]].depth)
				swap(x, y);
			sol = max(sol, query(0, whatPos[x], whatPath[x], 0, Paths[whatPath[x]].array.size() - 1, 1));
			x = Paths[whatPath[x]].parent;
//			printf("%d %d\n", x, y);
			}
		}

		fout << sol << '\n';
	}
	
}

int main() {
	ifstream fin("heavypath.in");
	int i, j, X, Y;
	fin >> n >> m;
	for(i = 1; i <= n; ++i)
		fin >> x[i];
	for(i = 1; i <= n; ++i)
		d[i] = 1;

	for(i = 1;  i < n ; ++i){
		fin >> X >> Y;
		a[X].push_back(Y);
		a[Y].push_back(X);
	}
	Paths.reserve(N);
	dfs(1);	
	
	ARB_INT.reserve(Paths.size());
	ARB_INT.resize(Paths.size());
//	for(i = 1; i <= n; ++i)
//		fout << i << " " << whatPath[i] << '\n';

	for(i = 0 ; i < Paths.size(); ++i) {
		reverse(Paths[i].array.begin(), Paths[i].array.end());
		for(j = 0; j < Paths[i].array.size(); ++j)
			whatPos[Paths[i].array[j]] = j;
		Paths[i].depth = DEPTH[Paths[i].array[0]];
		Paths[i].parent = t[Paths[i].parent];
	//	fout << i << " " << Paths[i].parent << " " <<  Paths[i].depth << '\n';
	//	for(j = 0; j < Paths[i].array.size(); ++j)
	//		fout << Paths[i].array[j] << '\n';

		ARB_INT[i].reserve(Paths[i].array.size() * 4 + 1);
		ARB_INT[i].resize(Paths[i].array.size() * 4 + 1);
	}

	for(i = 1; i <= n; ++i)
		update(x[i], whatPath[i],whatPos[i], 0, Paths[whatPath[i]].array.size()- 1, 1);
	/*
	for(i = 0; i < ARB_INT.size(); ++i){
		for(j = 1; j < ARB_INT[i].size(); ++j)
			fout <<j << " " <<  ARB_INT[i][j] << '\n';
		fout << '\n';
	}
	*/

	for(i = 1; i <= m; ++i){
		fin >> op[i].t >> op[i].x >> op[i].y;
		solve(i);
	}

	return 0;
}