Cod sursa(job #626669)

Utilizator cosmyoPaunel Cosmin cosmyo Data 27 octombrie 2011 21:23:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.23 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){
		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)
		::x[op[ind].x] = op[ind].y, 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;
	
		while(x != y) {
			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;
			}
		}
		sol = max(sol, ::x[x]);
		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 = 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];

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

	for(i = 1; i <= n; ++i)
		update(x[i], whatPath[i],whatPos[i], 0, Paths[whatPath[i]].array.size()- 1, 1);

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

	return 0;
}