#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int maxn = 100000 + 5;
vector<int> adj[maxn];
int n, q;
int vals[maxn];
int parent[maxn], depth[maxn];
int subtree[maxn], heavy[maxn];
int head[maxn], pos[maxn];
int cur_pos;
int seg[4 * maxn];
int binary_lift[maxn][17];
void dfs(int nod, int par) {
parent[nod] = par;
subtree[nod] = 1;
heavy[nod] = -1;
binary_lift[nod][0] = par;
for (auto v : adj[nod]) {
if (v == par) continue;
depth[v] = depth[nod] + 1;
dfs(v, nod);
subtree[nod] += subtree[v];
if (heavy[nod] == -1 || subtree[v] > subtree[heavy[nod]])
heavy[nod] = v;
}
}
void decompose(int nod, int h) {
head[nod] = h;
pos[nod] = ++cur_pos;
if (heavy[nod] != -1)
decompose(heavy[nod], h);
for (auto v : adj[nod]) {
if (v == parent[nod] || v == heavy[nod]) continue;
decompose(v, v);
}
}
void update(int nod, int l, int r, int poz, int val) {
if (l == r) {
seg[nod] = val;
return;
}
int mid = (l + r) / 2;
if (poz <= mid)
update(nod * 2, l, mid, poz, val);
else
update(nod * 2 + 1, mid + 1, r, poz, val);
seg[nod] = max(seg[nod * 2], seg[nod * 2 + 1]);
}
int query(int nod, int l, int r, int st, int dr) {
if (l > dr || r < st) return 0;
if (l >= st && r <= dr) return seg[nod];
int mid = (l + r) / 2;
return max(query(nod * 2, l, mid, st, dr),
query(nod * 2 + 1, mid + 1, r, st, dr));
}
int lca(int u, int v) {
if (depth[u] < depth[v]) swap(u, v);
for (int i = 16; i >= 0; i--) {
if (depth[binary_lift[u][i]] >= depth[v])
u = binary_lift[u][i];
}
if (u == v) return u;
for (int i = 16; i >= 0; i--) {
if (binary_lift[u][i] != binary_lift[v][i]) {
u = binary_lift[u][i];
v = binary_lift[v][i];
}
}
return parent[u];
}
int solve(int u, int v) {
int ans = 0;
while (head[u] != head[v]) {
if (depth[head[u]] < depth[head[v]])
swap(u, v);
ans = max(ans, query(1, 1, n, pos[head[u]], pos[u]));
u = parent[head[u]];
}
if (depth[u] > depth[v]) swap(u, v);
ans = max(ans, query(1, 1, n, pos[u], pos[v]));
return ans;
}
signed main() {
cin >> n >> q;
for (int i = 1; i <= n; i++)
cin >> vals[i];
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
dfs(1, 0);
decompose(1, 1);
for (int j = 1; j <= 16; j++) {
for (int i = 1; i <= n; i++) {
binary_lift[i][j] =
binary_lift[binary_lift[i][j - 1]][j - 1];
}
}
for (int i = 1; i <= n; i++)
update(1, 1, n, pos[i], vals[i]);
while (q--) {
int t, x, y;
cin >> t >> x >> y;
if (t == 0) {
update(1, 1, n, pos[x], y);
} else {
int lc = lca(x, y);
cout << max(solve(x, lc), solve(y, lc)) << '\n';
}
}
return 0;
}