#include <bits/stdc++.h>
#define L (pos << 1)
#define R (L | 1)
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
//struct chain {
// int sz;
// vector <int> data;
// void init() {
// data.resize(4 * sz + 100);
// }
// void upd(int st, int dr, int pos, int id, int val) {
// if (st == dr) {
// data[pos] = val;
// return;
// }
// int mid = st + dr >> 1;
// if (id <= mid)
// upd(st, mid, L, id, val);
// else upd(mid + 1, dr, R, id, val);
// data[pos] = max(data[L], data[R]);
// }
// int que(int st, int dr, int pos, int l, int r) {
// if (l <= st && dr <= r)
// return data[pos];
// int mid = st + dr >> 1;
// int lft = 0, rgt = 0;
// if (l <= mid)
// lft = que(st, mid, L, l, r);
// if (r > mid)
// rgt = que(mid + 1, dr, R, l, r);
// return max(lft, rgt);
// }
//};
int n, m, x, y, vf, t;
int viz[100100], niv[100100], dim[100100], a[100100], pos[100100], wh[100100], nr[100100];
int cnt, id[100100], dad[100100];
vector <int> v[100100], g[100100];
vector <int> ch[100100];
void upd(int tip, int st, int dr, int pos, int id, int val) {
if (st == dr) {
ch[tip][pos] = val;
return;
}
int mid = st + dr >> 1;
if (id <= mid)
upd(tip, st, mid, L, id, val);
else upd(tip, mid + 1, dr, R, id, val);
ch[tip][pos] = max(ch[tip][L], ch[tip][R]);
}
int que(int tip, int st, int dr, int pos, int l, int r) {
if (l <= st && dr <= r)
return ch[tip][pos];
int mid = st + dr >> 1;
int lft = 0, rgt = 0;
if (l <= mid)
lft = que(tip, st, mid, L, l, r);
if (r > mid)
rgt = que(tip, mid + 1, dr, R, l, r);
return max(lft, rgt);
}
void calc(int x) {
viz[x] = 1;
dim[x] = 1;
for (auto y : v[x])
if (!viz[y]) {
calc(y);
dim[x] += dim[y];
}
}
void dfs(int x, int lvl) {
viz[x] = 1;
pos[x] = vf;
niv[x] = lvl;
int mx = 0, p = 0;
for (auto y : v[x])
if (!viz[y]) {
dad[y] = x;
dfs(y, lvl + 1);
if (dim[y] > mx) {
mx = dim[y];
p = y;
}
}
if (!p) {
++cnt;
id[x] = cnt;
g[cnt].push_back(x);
} else {
id[x] = id[p];
g[id[x]].push_back(x);
}
}
void hld() {
for (int i = 1; i <= cnt; i++) {
int sz = g[i].size();
// ch[i].sz = sz;
// ch[i].init();
nr[i] = sz;
ch[i].resize(4 * sz + 1);
for (int j = 0; j < sz; j++) {
// ch[i].upd(1, sz, 1, j + 1, a[g[i][j]]);
upd(i, 1, sz, 1, j + 1, a[g[i][j]]);
wh[g[i][j]] = j + 1;
}
}
}
int solve(int x, int y) {
int ans = 0, dadx, dady, sz;
while (id[x] != id[y]) {
// dadx = g[id[x]][ch[id[x]].sz - 1];
// dady = g[id[y]][ch[id[y]].sz - 1];
dadx = g[id[x]][nr[id[x]] - 1];
dady = g[id[y]][nr[id[y]] - 1];
if (niv[dadx] > niv[dady]) {
// sz = ch[id[x]].sz;
// ans = max(ans, ch[id[x]].que(1, sz, 1, wh[x], sz));
sz = nr[id[x]];
ans = max(ans, que(id[x], 1, sz, 1, wh[x], sz));
x = dad[dadx];
} else {
// sz = ch[id[y]].sz;
// ans = max(ans, ch[id[y]].que(1, sz, 1, wh[y], sz));
sz = nr[id[y]];
ans = max(ans, que(id[y], 1, sz, 1, wh[y], sz));
y = dad[dady];
}
}
if (wh[x] > wh[y])
swap(x, y);
// ans = max(ans, ch[id[x]].que(1, ch[id[x]].sz, 1, wh[x], wh[y]));
ans = max(ans, que(id[x], 1, nr[id[x]], 1, wh[x], wh[y]));
return ans;
}
int main() {
in >> n >> m;
for (int i = 1; i <= n; i++)
in >> a[i];
for (int i = 1; i < n; i++) {
in >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
calc(1);
memset(viz, 0, sizeof viz);
dfs(1, 1);
niv[0] = 2e9;
hld();
while (m--) {
in >> t >> x >> y;
if (t == 0) {
a[x] = y;
// ch[id[x]].upd(1, ch[id[x]].sz, 1, wh[x], y);
upd(id[x], 1, nr[id[x]], 1, wh[x], y);
} else {
out << solve(x, y) << '\n';
}
}
return 0;
}