#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int N = (int)1e5 + 7;
int n, m;
int sub[N];
vector <int> g[N];
int a[N];
bool heavy[N];
int par[N];
int dep[N];
int ids[N];
int who[N];
int pos[N];
int bg[N];
bool cmp(int i, int j) {
return dep[i] > dep[j];
}
void dfs(int nod) {
sub[nod] = 1;
for (auto &nou : g[nod])
if (sub[nou] == 0) {
dep[nou] = 1 + dep[nod];
dfs(nou);
sub[nod] += sub[nou];
} else
par[nod] = nou;
for (auto &nou : g[nod])
if (nou != par[nod] && sub[nou] >= sub[nod] / 2)
heavy[nou] = 1;
}
const int K = 19;
int euler[2 * N], top;
int first[N];
int last[N];
pair <int, int> rmq[K][2 * N];
int lg[2 * N];
void dfs_euler(int nod) {
euler[++top] = nod;
for (auto &nou : g[nod])
if (nou != par[nod]) {
dfs_euler(nou);
euler[++top] = nod;
}
}
int lca(int a, int b) {
if(first[a] > last[b])
swap(a, b);
int i = first[a];
int j = last[b];
int k = lg[j - i + 1];
return min(rmq[k][i], rmq[k][j - (1 << k) + 1]).second;
}
struct seg_tree {
vector <int> t;
int n;
void init(int __n) {
n = __n;
t.resize(4 * n + 1);
}
void upd(int v, int tl, int tr, int p, int x) {
if (tr < p || p < tl)
return;
if (tl == tr)
t[v] = x;
else {
int tm = (tl + tr) / 2;
upd(2 * v, tl, tm, p, x);
upd(2 * v + 1, tm + 1, tr, p, x);
t[v] = max(t[2 * v], t[2 * v + 1]);
}
}
void upd(int p, int x) {
upd(1, 0, n - 1, p, x);
}
int get(int v, int tl, int tr, int l, int r) {
if (tr < l || r < tl)
return -(1 << 30);
if (l <= tl && tr <= r)
return t[v];
else {
int tm = (tl + tr) / 2;
int a = get(2 * v, tl, tm, l, r);
int b = get(2 * v + 1, tm + 1, tr, l, r);
return max(a, b);
}
}
int get(int l, int r) {
return get(1, 0, n - 1, l, r);
}
};
vector <seg_tree> tt;
int hw[N];
int ask(int a, int b) {
int c = lca(a, b);
int ans = hw[c];
while (1) {
if (who[a] == who[c] || who[par[a]] == who[c]) {
int pc = pos[c];
int pa = pos[a];
int wt = who[a];
ans = max(ans, tt[wt].get(pc, pa));
break;
} else {
int pa = pos[a];
int wt = who[a];
ans = max(ans, tt[wt].get(0, pa));
a = par[bg[wt]];
}
}
a = b;
while (1) {
if (who[a] == who[c] || who[par[a]] == who[c]) {
int pc = pos[c];
int pa = pos[a];
int wt = who[a];
ans = max(ans, tt[wt].get(pc, pa));
break;
} else {
int pa = pos[a];
int wt = who[a];
ans = max(ans, tt[wt].get(0, pa));
a = par[bg[wt]];
}
}
return ans;
}
int main() {
freopen ("heavypath.in", "r", stdin);
freopen ("heavypath.out", "w", stdout);
for (int i = 2; i < 2 * N; i++)
lg[i] = 1 + lg[i / 2];
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
who[i] = -1;
ids[i] = i;
scanf("%d", &hw[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);
}
dfs(1);
dfs_euler(1);
for (int i = 1; i <= top; i++)
last[euler[i]] = i;
for (int i = top; i >= 1; i--)
first[euler[i]] = i;
for (int i = 1; i <= top; i++)
rmq[0][i] = {dep[euler[i]], euler[i]};
for (int k = 1; (1 << k) <= top; k++)
for (int i = 1; i + (1 << k) - 1 <= top; i++)
rmq[k][i] = min(rmq[k - 1][i], rmq[k - 1][i + (1 << (k - 1))]);
sort(ids + 1, ids + n + 1, cmp);
int now = -1;
for (int j = 1; j <= n; j++) {
int nod = ids[j];
if (who[nod] != -1)
continue;
now++;
vector <int> path;
int cnt_light = 0;
while (who[nod] == -1) {
if (heavy[nod] == 0) {
if (cnt_light == 1)
break;
cnt_light++;
}
path.push_back(nod);
who[nod] = now;
nod = par[nod];
}
reverse(path.begin(), path.end());
bg[now] = path[0];
int curp = -1;
tt.push_back({});
tt.back().init((int) path.size());
for (auto &nod : path) {
curp++;
tt.back().upd(curp, hw[nod]);
pos[nod] = curp;
}
}
while (m--) {
int qt, a, b;
scanf("%d %d %d", &qt, &a, &b);
if (qt == 0) {
int wt = who[a];
int pa = pos[a];
hw[a] = b;
tt[wt].upd(pa, b);
} else {
int ans = ask(a, b);
printf("%d\n", ans);
}
}
return 0;
}