// https://www.infoarena.ro/problema/heavypath
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int N = 1e5;
int n, q;
vector<vector<int>> adj;
vector<int> val;
vector<int> parent, sz, depth, heavy_child;
void dfs(int v, int p) {
parent[v] = p;
depth[v] = depth[p] + 1;
sz[v] = 1;
int max_sz = 0;
for (int u : adj[v]) {
if (u == p) continue;
dfs(u, v);
sz[v] += sz[u];
if (sz[u] > max_sz) {
max_sz = sz[u];
heavy_child[v] = u;
}
}
}
vector<int> heavy_head, heavy_order, where;
void decompose(int v, int head) {
heavy_head[v] = head;
where[v] = heavy_order.size();
heavy_order.push_back(v);
if (heavy_child[v]) decompose(heavy_child[v], head);
for (int u : adj[v]) {
if (u == parent[v] || u == heavy_child[v]) continue;
decompose(u, u);
}
}
vector<int> segtree;
void segtree_build(int v, int st, int dr) {
if (st == dr) segtree[v] = val[heavy_order[st]];
else {
int mid = (st + dr) / 2;
segtree_build(2 * v, st, mid);
segtree_build(2 * v + 1, mid + 1, dr);
segtree[v] = max(segtree[2 * v], segtree[2 * v + 1]);
}
}
void segtree_update(int v, int st, int dr, int poz, int x) {
if (st == dr) segtree[v] = x;
else {
int mid = (st + dr) / 2;
if (poz <= mid) segtree_update(2 * v, st, mid, poz, x);
else segtree_update(2 * v + 1, mid + 1, dr, poz, x);
segtree[v] = max(segtree[2 * v], segtree[2 * v + 1]);
}
}
int segtree_query(int v, int st, int dr, int l, int r) {
if (st >= l && dr <= r) return segtree[v];
int mid = (st + dr) / 2, res = 0;
if (l <= mid) res = max(res, segtree_query(2 * v, st, mid, l, r));
if (mid < r) res = max(res, segtree_query(2 * v + 1, mid + 1, dr, l, r));
return res;
}
int heavy_query(int u, int v) {
if (depth[u] > depth[v]) swap(u, v);
if (heavy_head[u] == heavy_head[v]) {
return segtree_query(1, 1, n, where[u], where[v]);
}
if (depth[heavy_head[v]] < depth[heavy_head[u]]) swap(u, v);
return max(
segtree_query(1, 1, n, where[heavy_head[v]], where[v]),
heavy_query(u, parent[heavy_head[v]])
);
}
int main() {
fin >> n >> q;
val.assign(n + 1, 0);
for (int i = 1; i <= n; ++i) fin >> val[i];
adj.assign(n + 1, {});
for (int i = 1; i <= n - 1; ++i) {
int u, v;
fin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
parent.assign(n + 1, 0);
sz.assign(n + 1, 0);
depth.assign(n + 1, 0);
heavy_child.assign(n + 1, 0);
dfs(1, 0);
heavy_head.assign(n + 1, 0);
heavy_order.assign(1, 0);
where.assign(n + 1, 0);
decompose(1, 1);
segtree.assign(4 * (n + 1), 0);
segtree_build(1, 1, n);
while (q--) {
int t, x, y;
fin >> t >> x >> y;
if (t == 0) {
segtree_update(1, 1, n, where[x], y);
} else {
fout << heavy_query(x, y) << endl;
}
}
}