Cod sursa(job #2352154)

Utilizator flibiaVisanu Cristian flibia Data 23 februarie 2019 00:41:23
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.7 kb
#include <bits/stdc++.h>
#define L (pos << 1)
#define R (L | 1)

using namespace std;

ifstream in("heavypath.in");
ofstream out("heavypath.out");

//struct chain {
//	int sz;	
//	vector <int> data;
//	void init() {
//		data.resize(4 * sz + 100);
//	}
//	void upd(int st, int dr, int pos, int id, int val) {
//		if (st == dr) {
//			data[pos] = val;
//			return;
//		}
//		int mid = st + dr >> 1;
//		if (id <= mid)
//			upd(st, mid, L, id, val);
//		else upd(mid + 1, dr, R, id, val);
//		data[pos] = max(data[L], data[R]);
//	}
//	int que(int st, int dr, int pos, int l, int r) {
//		if (l <= st && dr <= r)
//			return data[pos];
//		int mid = st + dr >> 1;
//		int lft = 0, rgt = 0;
//		if (l <= mid)
//			lft = que(st, mid, L, l, r);
//		if (r > mid)
//			rgt = que(mid + 1, dr, R, l, r);
//		return max(lft, rgt);
//	}
//};

int n, m, x, y, vf, t;
int viz[100100], niv[100100], dim[100100], a[100100], pos[100100], wh[100100], nr[100100];
int cnt, id[100100], dad[100100];
vector <int> v[100100], g[100100];
vector <int> ch[100100];

void upd(int tip, int st, int dr, int pos, int id, int val) {
	if (st == dr) {
		ch[tip][pos] = val;
		return;
	}
	int mid = st + dr >> 1;
	if (id <= mid)
		upd(tip, st, mid, L, id, val);
	else upd(tip, mid + 1, dr, R, id, val);
	ch[tip][pos] = max(ch[tip][L], ch[tip][R]);
}

int que(int tip, int st, int dr, int pos, int l, int r) {
	if (l <= st && dr <= r)
		return ch[tip][pos];
	int mid = st + dr >> 1;
	int lft = 0, rgt = 0;
	if (l <= mid)
		lft = que(tip, st, mid, L, l, r);
	if (r > mid)
		rgt = que(tip, mid + 1, dr, R, l, r);
	return max(lft, rgt);
}

void calc(int x) {
	viz[x] = 1;
	dim[x] = 1;
	for (auto y : v[x])
		if (!viz[y]) {
			calc(y);
			dim[x] += dim[y];
		}
}	

void dfs(int x, int lvl) {
	viz[x] = 1;
	pos[x] = vf;
	niv[x] = lvl;
	int mx = 0, p = 0;
	for (auto y : v[x])
		if (!viz[y]) {
			dad[y] = x;
			dfs(y, lvl + 1);
			if (dim[y] > mx) {
				mx = dim[y];
				p = y;
			}
		}
	if (!p) {
		++cnt;
		id[x] = cnt;
		g[cnt].push_back(x);
	} else {
		id[x] = id[p];
		g[id[x]].push_back(x);
	}
}

void hld() {
	for (int i = 1; i <= cnt; i++) {
		int sz = g[i].size();
	//	ch[i].sz = sz;
	//	ch[i].init();
		nr[i] = sz;
		ch[i].resize(4 * sz + 1);
		for (int j = 0; j < sz; j++) {
		//	ch[i].upd(1, sz, 1, j + 1, a[g[i][j]]);
			upd(i, 1, sz, 1, j + 1, a[g[i][j]]);
			wh[g[i][j]] = j + 1;
		}
	}	
}

int solve(int x, int y) {
	int ans = 0, dadx, dady, sz;
	while (id[x] != id[y]) {
	//	dadx = g[id[x]][ch[id[x]].sz - 1];
	//	dady = g[id[y]][ch[id[y]].sz - 1];
		dadx = g[id[x]][nr[id[x]] - 1];
		dady = g[id[y]][nr[id[y]] - 1];
		if (niv[dadx] > niv[dady]) {
		//	sz = ch[id[x]].sz;
		//	ans = max(ans, ch[id[x]].que(1, sz, 1, wh[x], sz));
			sz = nr[id[x]];
			ans = max(ans, que(id[x], 1, sz, 1, wh[x], sz));
			x = dad[dadx];
		} else {
		//	sz = ch[id[y]].sz;
		//	ans = max(ans, ch[id[y]].que(1, sz, 1, wh[y], sz));
			sz = nr[id[y]];
			ans = max(ans, que(id[y], 1, sz, 1, wh[y], sz));
			y = dad[dady];
		}
	}
	if (wh[x] > wh[y])
		swap(x, y);
//	ans = max(ans, ch[id[x]].que(1, ch[id[x]].sz, 1, wh[x], wh[y]));
	ans = max(ans, que(id[x], 1, nr[id[x]], 1, wh[x], wh[y]));
	return ans;
}

int main() {
	in >> n >> m;
	for (int i = 1; i <= n; i++)
		in >> a[i];
	for (int i = 1; i < n; i++) {
		in >> x >> y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	calc(1);
	memset(viz, 0, sizeof viz);
	dfs(1, 1);	
	niv[0] = 2e9;
	hld();
	while (m--) {
		in >> t >> x >> y;
		if (t == 0) {
			a[x] = y;
		//	ch[id[x]].upd(1, ch[id[x]].sz, 1, wh[x], y);
			upd(id[x], 1, nr[id[x]], 1, wh[x], y);
		} else {
			out << solve(x, y) << '\n';
		}
	}
	return 0;
}