Link to this code:
https://cses.fi/paste/5c9d34a012f8941682483f/#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct Segment {
int n;
vector<LL> t;
Segment() {}
Segment(vector<int> v) : n(v.size()) {
t.resize(2 * n);
for (int i = 0; i < n; ++i) t[i + n] = v[i];
for (int i = n-1; i > 0; --i) t[i] = max(t[2*i], t[2*i+1]);
}
void update(int p, int v) {
for (t[p += n] = v; p > 1; p >>= 1) {
t[p >> 1] = max(t[p], t[p ^ 1]);
}
}
LL query(int l, int r) {
LL ans = 0;
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
if (l & 1) ans = max(ans, t[l++]);
if (r & 1) ans = max(ans, t[--r]);
}
return ans;
}
};
struct Hld {
int n;
int cur_pos = 0;
vector<int> par;
vector<int> pos;
vector<int> size;
vector<int> head;
vector<int> depth;
vector<vector<int>> adj;
Segment seg;
Hld(vector<vector<int>> adj, vector<int> v) : n(adj.size()), adj(adj) {
par.assign(n, -1);
pos.assign(n, -1);
size.assign(n, 0);
head.assign(n, -1);
depth.assign(n, -1);
dfs(0);
decompose(0, 0);
seg = Segment(vector<int>(n, 0));
for (int i = 0; i < n; ++i) seg.update(pos[i], v[i]);
}
int dfs(int v) {
for (int& u : adj[v]) {
if (u == par[v]) continue;
par[u] = v;
depth[u] = depth[v] + 1;
size[v] += dfs(u);
}
sort(adj[v].begin(), adj[v].end(), [&](int i, int j){return size[i] > size[j];});
return size[v];
}
void decompose(int v, int h) {
head[v] = h;
pos[v] = cur_pos++;
bool heavy_found = false;
for (int u : adj[v]) {
if (u == par[v]) continue;
if (!heavy_found) {
heavy_found = true;
decompose(u, h);
} else {
decompose(u, u);
}
}
}
LL query(int a, int b) {
LL ans = 0;
while (head[a] != head[b]) {
if (depth[head[a]] > depth[head[b]]) swap(a, b);
ans = max(ans, seg.query(pos[head[b]], pos[b]+1));
b = par[head[b]];
}
if (depth[a] > depth[b]) swap(a, b);
ans = max(ans, seg.query(pos[a], pos[b]+1));
return ans;
}
void update(int p, int v) {
seg.update(pos[p], v);
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n; cin >> n;
int q; cin >> q;
vector<int> v(n);
for (int i = 0; i < n; ++i) {
cin >> v[i];
}
vector<vector<int>> adj(n);
for (int i = 0, a, b; i < n - 1; ++i) {
cin >> a >> b; --a; --b;
adj[a].push_back(b);
adj[b].push_back(a);
}
Hld hld(adj, v);
for (int i = 0, t, a, b; i < q; ++i) {
cin >> t >> a >> b;
if (t == 1) {
hld.update(--a, b);
} else {
--a; --b;
cout << hld.query(a, b) << " ";
}
}
}