#include <bits/stdc++.h>
#define NMAX 100000
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, q, x, y, op, ans;
int val[NMAX + 3];
vector<int> arb[NMAX + 3];
bitset<NMAX + 3> viz;
int niv[NMAX + 3], sz[NMAX + 3];
int nr_L, L[NMAX + 3], Lrad[NMAX + 3], Lniv[NMAX + 3], Ldecal[NMAX + 3];
vector<int> Lant[NMAX + 3];
int tree[NMAX * 4 + 3];
void DFS(int nod) {
int frunza = 1, max_d = -1;
viz[nod] = 1;
sz[nod] = 1;
for (int vec : arb[nod]) {
if (viz[vec]) {
continue;
}
frunza = 0;
niv[vec] = niv[nod] + 1;
DFS(vec);
sz[nod] += sz[vec];
if (max_d == -1 || sz[max_d] < sz[vec]) {
max_d = vec;
}
}
if (frunza) {
nr_L++;
L[nod] = nr_L;
Lant[L[nod]].push_back(nod);
}
else {
L[nod] = L[max_d];
Lant[L[nod]].push_back(nod);
for (int vec : arb[nod]) {
if (vec == max_d || niv[vec] < niv[nod]) {
continue;
}
Lrad[L[vec]] = nod;
Lniv[L[vec]] = niv[nod];
}
}
}
void build_tree(int st, int dr, int node, int decal, int poz_l) {
if (st == dr) {
tree[node + decal] = val[Lant[poz_l][st - 1]];
return;
}
int mij = (st + dr) >> 1;
build_tree(st, mij, (node << 1), decal, poz_l);
build_tree(mij + 1, dr, (node << 1) + 1, decal, poz_l);
tree[node + decal] = max(tree[(node << 1) + decal], tree[(node << 1) + 1 + decal]);
}
void update(int st, int dr, int node, int poz, int val, int decal) {
if (st == dr) {
tree[node + decal] = val;
return;
}
int mij = (st + dr) >> 1;
if (poz <= mij) {
update(st, mij, (node << 1), poz, val, decal);
}
else {
update(mij + 1, dr, (node << 1) + 1, poz, val, decal);
}
tree[node + decal] = max(tree[(node << 1) + decal], tree[(node << 1) + 1 + decal]);
}
int max_query(int st, int dr, int node, int a, int b, int decal) {
if (dr < a || st > b) {
return INT_MIN;
}
if (a <= st && dr <= b) {
return tree[node + decal];
}
int mij = (st + dr) >> 1;
return max(max_query(st, mij, (node << 1), a, b, decal), max_query(mij + 1, dr, (node << 1) + 1, a, b, decal));
}
void build_chains() {
niv[1] = 1;
DFS(1);
for (int i = 1; i <= nr_L; i++) {
reverse(Lant[i].begin(), Lant[i].end());
if (i > 1) {
Ldecal[i] = Ldecal[i - 1] + Lant[i].size() * 4;
}
build_tree(1, Lant[i].size(), 1, Ldecal[i], i);
}
}
void solve() {
fin >> op >> x >> y;
if (op == 0) {
update(1, Lant[L[x]].size(), 1, niv[x] - Lniv[L[x]], y, Ldecal[L[x]]);
}
else {
ans = INT_MIN;
while (true) {
if (L[x] == L[y]) {
if (niv[x] > niv[y]) {
swap(x, y);
}
ans = max(ans, max_query(1, Lant[L[x]].size(), 1, niv[x] - Lniv[L[x]],
niv[y] - Lniv[L[y]], Ldecal[L[x]]));
break;
}
if (Lniv[L[x]] < Lniv[L[y]]) {
swap(x, y);
}
ans = max(ans, max_query(1, Lant[L[x]].size(), 1, 1, niv[x] - Lniv[L[x]], Ldecal[L[x]]));
x = Lrad[L[x]];
}
fout << ans << '\n';
}
}
int main() {
ios_base::sync_with_stdio(false);
fin.tie(NULL);
fout.tie(NULL);
fin >> n >> q;
for (int i = 1; i <= n; i++) {
fin >> val[i];
}
for (int i = 1; i <= n - 1; i++) {
fin >> x >> y;
arb[x].push_back(y);
arb[y].push_back(x);
}
build_chains();
while (q--) {
solve();
}
return 0;
}