#include <bits/stdc++.h>
using namespace std;
const int NMAX = 1e5 + 5;
const int INF = 2e9;
int n, m, nrLant;
int arb[4 * NMAX];
int pos[NMAX], tt[NMAX], sz[NMAX], heavy[NMAX], h[NMAX], val[NMAX], delta[NMAX], which[NMAX];
vector <int> v[NMAX], lant[NMAX];
void update(int delta, int pos, int val, int st, int dr, int nod = 1) {
if (st == dr) {
arb[nod + delta] = val;
return ;
}
int mij = (st + dr) / 2;
if (pos <= mij) update(delta, pos, val, st, mij, nod * 2);
else update(delta, pos, val, mij + 1, dr, nod * 2 + 1);
arb[nod + delta] = max(arb[nod * 2 + delta], arb[nod * 2 + 1 + delta]);
}
int query(int delta, int x, int y, int st, int dr, int nod = 1) {
if (x <= st && dr <= y) return arb[nod + delta];
int mij = (st + dr) / 2, ans = -INF;
if (x <= mij) ans = max(ans, query(delta, x, y, st, mij, nod * 2));
if (mij + 1 <= y) ans = max(ans, query(delta, x, y, mij + 1, dr, nod * 2 + 1));
return ans;
}
void dfs(int nod) {
sz[nod] = 1;
heavy[nod] = 0;
for (auto it : v[nod]) {
if (it == tt[nod]) continue ;
tt[it] = nod;
h[it] = h[nod] + 1;
dfs(it);
sz[nod] += sz[it];
if (heavy[nod] == 0 || sz[it] > sz[heavy[nod]]) heavy[nod] = it;
}
}
void decompose(int nod, int whichLant) {
lant[whichLant].push_back(nod);
which[nod] = whichLant;
pos[nod] = (int)lant[whichLant].size() - 1;
if (heavy[nod] != 0) decompose(heavy[nod], whichLant);
for (auto it : v[nod]) {
if (it == tt[nod] || it == heavy[nod]) continue ;
decompose(it, ++nrLant);
}
}
void buildLant() {
int sum = 0;
for (int i = 1; i <= nrLant ; ++i) {
delta[i] = sum;
for (auto nod : lant[i])
update(delta[i], pos[nod] + 1, val[nod], 1, (int)lant[i].size());
sum += (int)lant[i].size() * 4;
}
}
int getHeightLant(int nod) {
return h[lant[which[nod]][0]];
}
int queryLant(int x, int y) {
int ans = -INF;
while (which[x] != which[y]) {
if (getHeightLant(x) < getHeightLant(y)) swap(x, y);
int ind = which[x];
ans = max(ans, query(delta[ind], 1, pos[x] + 1, 1, (int)lant[ind].size()));
x = tt[lant[ind][0]];
}
///nodurile mele sunt pe acelasi lant
ans = max(ans, query(delta[which[x]], min(pos[x], pos[y]) + 1, max(pos[x], pos[y]) + 1, 1, (int)lant[which[x]].size()));
return ans;
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n ; ++i)
scanf("%d", &val[i]);
int x, y;
for (int i = 1; i < n ; ++i) {
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1);
decompose(1, ++nrLant);
buildLant();
int tip;
while (m--) {
scanf("%d%d%d", &tip, &x, &y);
if (tip == 0) {
val[x] = y;
update(delta[which[x]], pos[x] + 1, val[x], 1, (int)lant[which[x]].size());
} else if (tip == 1) printf("%d\n", queryLant(x, y));
}
return 0;
}