#include <bits/stdc++.h>
#define MN 107171
using namespace std;
ifstream fi("heavypath.in");
ofstream fo("heavypath.out");
int n, m, Val[MN];
vector<int> L[MN];
struct AINT {
int V[3 * MN];
void build(int u, int s, int d, int* O) {
if(s == d) {
V[u] = O[s];
return;
}
build(u * 2, s, (s + d) / 2, O);
build(u * 2 + 1, (s + d) / 2 + 1, d, O);
V[u] = max(V[u * 2], V[u * 2 + 1]);
}
void update(int p, int v, int u = 1, int s = 1, int d = MN - 1) {
if(d < p || p < s) return;
if(s == d) {
V[u] = v;
return;
}
update(p, v, u * 2, s, (s + d) / 2);
update(p, v, u * 2 + 1, (s + d) / 2 + 1, d);
V[u] = max(V[u * 2], V[u * 2 + 1]);
}
int query(int l, int r, int u = 1, int s = 1, int d = MN - 1) {
if(d < l || r < s) return 0;
if(l <= s && d <= r) return V[u];
return max(query(l, r, u * 2, s, (s + d) / 2), query(l, r, u * 2 + 1, (s + d) / 2 + 1, d));
}
};
struct HeavyPath {
AINT Arbore;
int Sum[MN], Niv[MN];
int nrseg, St[MN], Nr[MN], H[MN], Cul[MN]; // AINT
int PaterFam[MN], Par[MN];
// int lca(int u, int v) {
// if(Niv[u] < Niv[v]) swap(u, v);
// for(int k = 16, d = Niv[u] - Niv[v]; k >= 0; --k)
// if(d & (1 << k)) u = ST[k][u];
// if(u == v) return u;
// for(int k = 16; k >= 0; --k)
// if(ST[k][u] != ST[k][v]) u = ST[k][u], v = ST[k][v];
// return ST[0][u];
// }
void id_dfs(int u, int p, int niv) {
Sum[u] = 1;
Niv[u] = niv;
for(auto it : L[u]) if (it != p) {
id_dfs(it, u, niv + 1);
Sum[u] += Sum[it];
}
}
void cul_dfs(int u, int p, int color, int h) {
++Nr[color];
Cul[u] = color;
H[u] = h;
if(!h) PaterFam[color] = u;
Par[u] = p;
int ma = 0, sma = -1;
for(auto it : L[u]) if (it != p && Sum[it] > sma) {
sma = Sum[it];
ma = it;
}
for(auto it : L[u]) if (it != p) {
if(it == ma) cul_dfs(it, u, color, h + 1);
else cul_dfs(it, u, ++nrseg, 0);
}
}
void build() {
id_dfs(1, 0, 0);
cul_dfs(1, 0, (nrseg = 1), 0);
for(int i = 1; i <= nrseg; ++i) {
St[i] = Nr[i - 1] + 1;
Nr[i] += Nr[i - 1];
}
for(int i = 1; i <= n; ++i) Arbore.update(St[Cul[i]] + H[i], Val[i]);
// for(int k = 1; k < 17; ++k)
// for(int i = 1; i <= n; ++i) ST[k][i] = ST[k-1][ST[k-1][i]];
}
void update(int p, int v) { Arbore.update(St[Cul[p]] + H[p], v); }
// int solve(int fiu, int par) {
// if(Cul[fiu] == Cul[par]) return Arbore.query(St[Cul[par]] + H[par], St[Cul[fiu]] + H[fiu]);
// else return max(solve(fiu, PaterFam[Cul[fiu]]), solve(ST[0][PaterFam[Cul[fiu]]], par));
// }
int query(int u, int v) {
int re = 0;
while(1) {
if(Cul[u] == Cul[v])
return max(re, Arbore.query(St[Cul[u]] + min(H[u], H[v]), St[Cul[u]] + max(H[u], H[v])));
if(Niv[PaterFam[Cul[u]]] < Niv[PaterFam[Cul[v]]]) swap(u, v);
re = max(re, Arbore.query(St[Cul[u]], St[Cul[u]] + H[u]));
u = Par[PaterFam[Cul[u]]];
}
return re;
}
};
HeavyPath Sol;
int main() {
fi >> n >> m;
for(int i = 1; i <= n; ++i) fi >> Val[i];
for(int i = 1, u, v; i < n; ++i) {
fi >> u >> v;
L[u].push_back(v);
L[v].push_back(u);
}
Sol.build();
for(int i = 1, tip, a, b; i <= m; ++i) {
fi >> tip >> a >> b;
if(tip) fo << Sol.query(a, b) << "\n";
else Sol.update(a, b);
}
return 0;
}