Cod sursa(job #825263)

Utilizator ahmed.abdraboahmed.abdrabo ahmed.abdrabo Data 28 noiembrie 2012 02:35:41
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 2.83 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

const int H = 17;
const int MAX = 1 << H;

int M, N;
bool heavy[MAX];
int chain[MAX], depth[MAX], parent[MAX], pos[MAX], size[MAX], sorted[MAX], ST[MAX + MAX], V[MAX];
vector<int> chains[MAX];
vector<int> G[MAX];

struct cmp {
	bool operator()(const int & a, const int & b) const {
		return depth[a] < depth[b];
	}
};

void dfs(int u, int d = 0) {
	chain[u] = u;
	depth[u] = d;
	size[u] = 1;
	for (size_t i = 0; i < G[u].size(); i++) {
		int v = G[u][i];
		if (size[v] == 0) {
			dfs(v, d + 1);
			parent[v] = u;
			size[u] += size[v];
		}
	}
	for (size_t i = 0; i < G[u].size(); i++) {
		int v = G[u][i];
		if (parent[v] == u) {
			if (2 * size[v] >= size[u]) {
				heavy[v] = true;
			}
		}
	}
}

void hld(int u) {
	chain[u] = heavy[u] ? chain[parent[u]] : u;
	for (size_t i = 0; i < G[u].size(); i++) {
		int v = G[u][i];
		if (parent[v] == u) {
			hld(v);
		}
	}
}

int lca(int a, int b) {
	while (chain[a] != chain[b]) {
		if (depth[chain[a]] < depth[chain[b]]) {
			b = parent[chain[b]];
		} else {
			a = parent[chain[a]];
		}
	}
	return depth[a] < depth[b] ? a : b;
}

void set(int index, int value) {
	ST[index += MAX] = value;
	while (index > 1) {
		index >>= 1;
		ST[index] = max(ST[index << 1], ST[index << 1 | 1]);
	}
}

int get(int a, int b, int root = 1, int left = 0, int right = MAX) {
	if (left == a && b == right) {
		return ST[root];
	}
	int mid = (left + right) >> 1;
	if (b <= mid) {
		return get(a, b, root << 1, left, mid);
	}
	if (mid <= a) {
		return get(a, b, root << 1 | 1, mid, right);
	}
	return max(get(a, mid, root << 1, left, mid), get(mid, b, root << 1 | 1, mid, right));
}

int query(int x, int y) {
	int ans = V[x];
	while (x != y) {
		if (chain[x] == chain[y]) {
			ans = max(ans, get(pos[x], pos[y] + 1));
			y = x;
		} else {
			ans = max(ans, get(pos[chain[y]], pos[y] + 1));
			y = parent[chain[y]];
		}
	}
	return ans;
}

int main() {
	ifstream cin("heavypath.in");
	ofstream cout("heavypath.out");
	cin >> N >> M;
	for (int i = 1; i <= N; i++) {
		cin >> V[i];
	}
	for (int i = 2; i <= N; i++) {
		int a, b;
		cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	dfs(1);
	hld(1);
	for (int i = 1; i <= N; i++) {
		sorted[i] = i;
	}
	sort(sorted + 1, sorted + 1 + N, cmp());
	for (int i = 1; i <= N; i++) {
		chains[chain[sorted[i]]].push_back(sorted[i]);
	}
	for (int i = 1, c = 0; i <= N; i++) {
		for (size_t j = 0; j < chains[i].size(); j++) {
			pos[chains[i][j]] = c++;
			ST[pos[chains[i][j]] + MAX] = V[chains[i][j]];
		}
	}
	for (int i = MAX - 1; i > 0; i--) {
		ST[i] = max(ST[i << 1], ST[i << 1 | 1]);
	}
	for (int i = 1; i <= M; i++) {
		int t, x, y;
		cin >> t >> x >> y;
		if (t == 0) {
			V[x] = y;
			set(pos[x], y);
		}
		if (t == 1) {
			int p = lca(x, y);
			cout << max(query(p, x), query(p, y)) << endl;
		}
	}
	return 0;
}