#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
vector<int>G[MAXN + 5];
int sz[MAXN + 5];
int ind[MAXN + 5], nr[MAXN + 5];
vector<int>lant[MAXN + 5];
int vv[MAXN + 5];
int h[MAXN + 5];
int ff[MAXN + 5];
int nl;
int k1;
struct SegTree {
int n;
int* a;
SegTree(int x) {
n = x;
a = new int [4 * n + 5];
memset(a, 0, sizeof(a));
}
void build(vector<int>v) {
for (int i = 1; i <= n; ++i)
update(i, v[i - 1]);
}
void update(int poz, int val) {
u(1, 1, n, poz, val);
}
int query(int st, int dr) {
return q(1, 1, n, st, dr);
}
void u(int node, int st, int dr, int poz, int val) {
if (st == dr) {
a[node] = val;
return ;
}
int med = (st + dr) >> 1;
if (med >= poz)
u(2 * node, st, med, poz, val);
else
u(2 * node + 1, med + 1, dr, poz, val);
a[node] = max(a[2 * node], a[2 * node + 1]);
}
int q(int node, int st, int dr, int l, int r) {
if (l <= st && dr <= r)
return a[node];
int ans = 0;
int med = (st + dr >> 1);
if (l <= med)
ans = q(2 * node, st, med, l, r);
if (r > med)
ans = max(ans, q(2 * node + 1, med + 1, dr, l, r));
return ans;
}
};
void prec(int node, int f) {
sz[node] = 1;
h[node] = 1 + h[f];
ff[node] = f;
for (auto it:G[node])
if (it != f) {
prec(it, node);
sz[node] += sz[it];
}
}
void dfs(int node, int f, int k) {
nl = max(nl, k);
ind[node] = k;
lant[k].push_back(node);
nr[node] = lant[k].size();
int x = 0;
for (auto it:G[node])
if (it != f && sz[x] < sz[it])
x = it;
if (x)
dfs(x, node, k);
for (auto it:G[node])
if (it != f && it != x) {
k1++;
dfs(it, node, k1);
}
}
vector<SegTree>hp;
void update(int x, int y) {
hp[ind[x]].update(nr[x], y);
}
int query(int x, int y) {
if (ind[x] == ind[y]) {
if (h[x] > h[y])
swap(x, y);
return hp[ind[x]].query(nr[x], nr[y]);
}
if (h[lant[ind[x]][0]] < h[lant[ind[y]][0]])
swap(x, y);
return max(query(ff[lant[ind[x]][0]], y), hp[ind[x]].query(1, nr[x]));
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%d", &vv[i]);
for (int i = 1; i < n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
prec(1, 0);
dfs(1, 0, 0);
for (int i = 0; i <= nl; ++i) {
SegTree a(lant[i].size());
vector<int>aux;
for (auto it:lant[i])
aux.push_back(vv[it]);
a.build(aux);
hp.push_back(a);
}
for (int i = 1; i <= m; ++i) {
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
if (t == 0)
update(x, y);
else
printf("%d\n", query(x, y));
}
return 0;
}