Cod sursa(job #1198615)

Utilizator howsiweiHow Si Wei howsiwei Data 16 iunie 2014 13:37:15
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.79 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define PATH(u) paths[pathof[u]]
typedef pair<int, int> II;

vector<int> a;
vector<vector<int>> adjl;
vector<int> parent;
vector<int> level;
vector<int> leaf;
vector<int> pathof;
vector<int> index;

class Path
{
public:
	int n;
	vector<int> t;
	int root;
	Path() {}
	Path(int leaf, int root, int n) : n(n), root(root)
	{
		t.resize(2*n);
		for (int i = 2*n-1, u = leaf; i >= n; u = parent[u], i--) {
			t[i] = a[u];
		}
		for (int i = n-1; i > 0; i--) {
			t[i] = max(t[2*i], t[2*i+1]);
		}
		// printf("%d\n", n);
		// for (int i = 1; i < 2*n; i++) {
		// 	printf("%d ", t[i]);
		// }
		// puts("");
	}
	int getmax(int hi)
	{
		if (hi == n-1) {
			return t[1];
		}
		else {
			return getmax(0, hi);
		}
	}
	int getmax(int lo, int hi)
	{
		lo += n;
		hi += n;
		int res = 0;
		while (lo < hi) {
			if (lo & 1) {
				res = max(res, t[lo]);
				lo >>= 1;
				lo++;
			}
			else {
				lo >>= 1;
			}
			if (hi & 1) {
				hi >>= 1;
			}
			else {
				res = max(res, t[hi]);
				hi >>= 1;
				hi--;
			}
		}
		if (lo == hi) {
			res = max(res, t[lo]);
		}
		return res;
	}
	void update(int idx, int val)
	{
		idx += n;
		t[idx] = val;
		while (idx > 1) {
			val = max(t[idx], t[idx^1]);
			idx >>= 1;
			if (t[idx] == val) {
				break;
			}
			else {
				t[idx] = val;
			}
		}
	}
};

vector<Path> paths;

void build_path(int l, int r)
{
	int len = 0;
	for (int u = l; ; u = parent[u], len++) {
		pathof[u] = paths.size();
		index[u] = len;
		if (u == r) {
			len++;
			break;
		}
	}
	for (int u = l, i = len-1; i >= 0; u = parent[u], i--) {
		index[u] = i;
	}
	paths.emplace_back(l, r, len);
	// puts("asdf");
}

int build_heavy_paths(int u)
{
	int size = 1;
	if (adjl[u].size() == (u == 0 ? 0 : 1)) {
		leaf[u] = u;
	}
	else {
		II heaviest = {0, 0};
		for (auto v: adjl[u]) {
			if (v == parent[u]) {
				continue;
			}
			parent[v] = u;
			level[v] = level[u]+1;
			int subsize = build_heavy_paths(v);
			size += subsize;
			heaviest = max(heaviest, {subsize, v});
		}
		leaf[u] = leaf[heaviest.second];
		for (auto v: adjl[u]) {
			if (v == parent[u] || v == heaviest.second) {
				continue;
			}
			else {
				build_path(leaf[v], v);
			}
		}
	}
	if (u == 0) {
		build_path(leaf[u], u);
	}
	return size;
}

int getmax(int u, int v)
{
	int res = 0;
	while (pathof[u] != pathof[v]) {
		if (level[PATH(u).root] > level[PATH(v).root]) {
			swap(u, v);
		}
		res = max(res, PATH(v).getmax(index[v]));
		v = parent[PATH(v).root];
	}
	II x = minmax(index[u], index[v]);
	res = max(res, PATH(v).getmax(x.first, x.second));
	return res;
}

void update(int u, int val)
{
	PATH(u).update(index[u], val);
}

int main()
{
	ios::sync_with_stdio(false);
	freopen("heavypath.in", "r", stdin);
	freopen("heavypath.out", "w", stdout);
	int n, m;
	cin >> n >> m;
	a.resize(n);
	for (auto & x: a) {
		cin >> x;
	}
	adjl.resize(n);
	for (int i = 0; i < n-1; i++) {
		int u, v;
		cin >> u >> v;
		u--, v--;
		adjl[u].push_back(v);
		adjl[v].push_back(u);
	}
	parent.resize(n);
	parent[0] = -1;
	level.resize(n);
	leaf.resize(n);
	pathof.resize(n);
	index.resize(n);
	build_heavy_paths(0);
	// for (auto x: leaf) {
	// 	printf("%d ", x);
	// }
	// puts("");
	// for (auto x: level) {
	// 	printf("%d ", x);
	// }
	// puts("");
	// for (auto x: pathof) {
	// 	printf("%d ", x);
	// }
	// puts("");
	// for (auto x: index) {
	// 	printf("%d ", x);
	// }
	// puts("");
	// printf("%d\n", getmax(3, 6));
	// printf("%d\n", paths[3].getmax(0, 3));
	// printf("%d\n", paths[3].getmax(3));
	// printf("%d\n", paths[3].t[1]);
	// printf("%d\n", paths[3].n);
	// return 0;
	for (int i = 0; i < m; i++) {
		int op;
		cin >> op;
		if (op == 0) {
			int u, val;
			cin >> u >> val;
			u--;
			update(u, val);
		}
		else {
			int u, v;
			cin >> u >> v;
			u--, v--;
			printf("%d\n", getmax(u, v));
		}
	}
	return 0;
}