Cod sursa(job #2753289)

Utilizator Cristian1997Vintur Cristian Cristian1997 Data 22 mai 2021 11:12:25
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.34 kb
#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define dbg(...) cerr << #__VA_ARGS__ << " ->", debug_out(__VA_ARGS__)
#define dbg_p(x) cerr<<#x": "<<(x).first<<' '<<(x).second<<endl
#define dbg_v(x, n) {cerr<<#x"[]: ";for(long long _=0;_<n;++_)cerr<<(x)[_]<<' ';cerr<<endl;}
#define all(v) v.begin(), v.end()
#define fi first
#define se second
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << H; debug_out(T...);}

template<typename T1, typename T2>
ostream& operator <<(ostream &out, const pair<T1, T2> &item) {
	out << '(' << item.first << ", " << item.second << ')';
	return out;
}

template <typename T>
ostream& operator <<(ostream &out, const vector<T>& v) {
	for(const auto &item : v) out << item << ' ';
	return out;
}

struct SegTree {
	int n;
	vector<int> st;
	
	SegTree(int n) : n(n), st(2 * n) {}

	void update(int p, int val) {
		for(st[p += n] = val; p > 1; p >>= 1) st[p >> 1] = max(st[p], st[p ^ 1]);
	}

	int query(int l, int r) {
		int res = 0;
		for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
			if(l & 1) res = max(res, st[l++]);
			if(r & 1) res = max(res, st[--r]);
		}
		return res;
	}
};

struct HLD {
	int n, t;
	vector<int> in, out, head, fth, h, sz;
	vector<vector<int>> adj;
	SegTree segTree;
	// in[i] = time entering node i
	// out[i] = time leaving node i
	// head[i] = head of path containing node i
	// fth[i] = parent of node i in original tree
	// h[i] = height of node i in original tree starting from 0
	// sz[i] = size of subtree of i in original tree

	HLD(int n) : n(n), in(n), out(n), head(n), fth(n), h(n), sz(n), adj(n), segTree(n) {}

	void addEdge(int a, int b) {
		adj[a].push_back(b);
		adj[b].push_back(a);
	}

	void dfsSize(int v, int p = -1) {
		sz[v] = 1;
		for(auto &u : adj[v])
			if(u != p) {
				fth[u] = v;
				h[u] = 1 + h[v];
				dfsSize(u, v);
				sz[v] += sz[u];
				if(sz[u] > sz[adj[v][0]]) swap(u, adj[v][0]);
			}
	}

	void dfsHld(int v, int p = -1) {
		in[v] = t++;
		for(auto u : adj[v])
			if(u != p) {
				head[u] = (u == adj[v][0] ? head[v] : u);
				dfsHld(u, v);
			}
		out[v] = t;
	}

	void build(const vector<int> &v) {
		t = 0;
		sz.assign(n, 0);

		dfsSize(0);
		dfsHld(0);
	
		for(int i = 0; i < n; ++i) segTree.update(in[i], v[i]);
	}

	void update(int v, int val) {
		segTree.update(in[v], val);
	}

	int query(int v, int u) {
		int res = 0;
		while(head[v] != head[u]) {
			if(h[head[v]] > h[head[u]]) swap(v, u);

			res = max(res, segTree.query(in[head[u]], in[u] + 1));
			u = fth[head[u]];
		}

		if(h[v] > h[u]) swap(v, u);
		res = max(res, segTree.query(in[v], in[u] + 1));

		return res;
	}

	// subtree of v: [in_v, out_v)
	// path from v to the heavy path head: [in_head_v, in_v]
};

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	freopen("heavypath.in", "r", stdin);
	freopen("heavypath.out", "w", stdout);

	int n, m, a, b, t, x, y;

	cin >> n >> m;

	vector<int> v(n);
	for(int i = 0; i < n; ++i) cin >> v[i];

	HLD hld(n);
	for(int i = 1; i < n; ++i) {
		cin >> a >> b; --a; --b;
		hld.addEdge(a, b);
	}

	hld.build(v);

	while(m--) {
		cin >> t >> x >> y;

		if(t == 0) hld.update(x - 1, y);
		else {
			cout << hld.query(x - 1, y - 1) << '\n';
		}
	}

	return 0;
}