Cod sursa(job #1397536)

Utilizator Mihai22eMihai Ionut Enache Mihai22e Data 23 martie 2015 16:32:05
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.16 kb
#include <vector>
#include <algorithm>

#include <cstdio>
using namespace std;

const int MAX_N = 100002;

int N, M, nP;
int F[MAX_N], Lv[MAX_N], W[MAX_N], val[MAX_N];
pair < int, int > pos[MAX_N];
vector < int > v[MAX_N], Aint[MAX_N], Path[MAX_N];
bool vis[MAX_N];

void DFS(int x) {
	vis[x] = 1;
	W[x]++;
	
	int z = 0;
	for(int i = 0; i < (int) v[x].size(); ++i) {
		int y = v[x][i];

		if(vis[y])
			continue;
		
		F[y] = x;
		Lv[y] = Lv[x] + 1;
		DFS(y);

		W[x] += W[y];

		if(z == 0 || W[y] > W[z])
			z = y;
	}

	if(z == 0) {
		++nP;
		Path[nP].push_back(x);
		pos[x].first = nP;
	}
	else {
		Path[pos[z].first].push_back(x);
		pos[x].first = pos[z].first;
	}
}

void build(int ind, int node, int left, int right) {
	if(left == right) 
		Aint[ind][node] = val[Path[ind][left]];
	else {
		int ls = 2 * node, rs = 2 * node + 1, m = (left + right) / 2;
		
		build(ind, ls, left, m);
		build(ind, rs, m + 1, right);

		Aint[ind][node] = max(Aint[ind][ls], Aint[ind][rs]);
	}
}

void makePaths() {
	Lv[1] = 1;
	DFS(1);

	for(int i = 1; i <= nP; ++i) {
		Path[i].push_back(0);
		
		reverse(Path[i].begin(), Path[i].end());

		int n = Path[i].size() - 1;
		for(int j = 1; j <= n; ++j)
			pos[Path[i][j]].second = j;
		
		for(int j = 0; j <= 4 * n; ++j)
			Aint[i].push_back(0);
		build(i, 1, 1, n);
	}
}

int update(int ind, int node, int left, int right, int x, int y) {
	if(left == right)
		Aint[ind][node] = y;
	else {
		int ls = 2 * node, rs = 2 * node + 1, m = (left + right) / 2;
		
		if(x <= m)
			update(ind, ls, left, m, x, y);
		else update(ind, rs, m + 1, right, x, y);

		Aint[ind][node] = max(Aint[ind][ls], Aint[ind][rs]);
	}
}

int query(int ind, int node, int left, int right, int x, int y) {
	int ret = 0;

	if(x <= left && right <= y) 
		ret = Aint[ind][node];
	else {
		int ls = 2 * node, rs = 2 * node + 1, m = (left + right) / 2;

		if(x <= m)
			ret = query(ind, ls, left, m, x, y);
		if(y > m)
			ret = max(ret, query(ind, rs, m + 1, right, x, y));
	}

	return ret;
}


int main() {
	freopen("heavypath.in", "r", stdin);
	freopen("heavypath.out", "w", stdout);
	
	scanf("%d %d", &N, &M);
	for(int i = 1; i <= N; ++i)
		scanf("%d", &val[i]);
	for(int i = 1; i < N; ++i) {
		int x, y;
		
		scanf("%d %d", &x, &y);
		
		v[x].push_back(y);
		v[y].push_back(x);
	}

	makePaths();

	for(int q = 1; q <= M; ++q) {
		int t, x, y;
		
		scanf("%d %d %d", &t, &x, &y);
		
		if(t == 0) {
			int ind = pos[x].first, p = pos[x].second;

			update(ind, 1, 1, Path[ind].size() - 1, p, y);
		}
		else {
			int ans = 0;
			bool ok = 1;

			while(ok) {
				if(pos[x].first == pos[y].first) {
					if(Lv[x] > Lv[y])
						swap(x, y);
					
					int ind = pos[x].first, px = pos[x].second, py = pos[y].second;
					int n = Path[ind].size() - 1;
					ans = max(ans, query(ind, 1, 1, n, px, py));

					ok = 0;
				}
				else {
					int indx = pos[x].first, indy = pos[y].first, fx = 0, fy = 0;
					
					fx = F[Path[indx][1]];
					fy = F[Path[indy][1]];
					
					if(Lv[fx] < Lv[fy]) {
						swap(x, y);
						swap(indx, indy);
						swap(fx, fy);
					}

					int px = pos[x].second, n = Path[indx].size() - 1;
					ans = max(ans, query(indx, 1, 1, n, 1, px));
					x = fx;
				}
			}

			printf("%d\n", ans);
		}
	}
	
	return 0;
}