#include <bits/stdc++.h>
#define NMAX 100000
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, q, op, x, y, ord;
int val[NMAX + 3], val_dfs[NMAX + 3];
vector<int> arb[NMAX + 3];
int par[NMAX + 3], niv[NMAX + 3], sz[NMAX + 3], heavy[NMAX + 3], head[NMAX + 3], poz[NMAX + 3];
int tree[NMAX * 4 + 3];
void dfs(int nod, int p) {
par[nod] = p;
sz[nod] = 1;
int sz_max = 0;
for (int vec : arb[nod]) {
if (vec == p) {
continue;
}
niv[vec] = niv[nod] + 1;
dfs(vec, nod);
sz[nod] += sz[vec];
if (sz[vec] > sz_max) {
sz_max = sz[vec];
heavy[nod] = vec;
}
}
}
void decompose(int nod, int p) {
head[nod] = p;
poz[nod] = ++ord;
val_dfs[ord] = val[nod];
if (heavy[nod]) {
decompose(heavy[nod], p);
}
for (int vec : arb[nod]) {
if (vec != par[nod] && vec != heavy[nod]) {
decompose(vec, vec);
}
}
}
void build_tree(int st, int dr, int node) {
if (st == dr) {
tree[node] = val_dfs[st];
return;
}
int mij = (st + dr) >> 1;
build_tree(st, mij, (node << 1));
build_tree(mij + 1, dr, (node << 1) + 1);
tree[node] = max(tree[(node << 1)], tree[(node << 1) + 1]);
}
void update(int st, int dr, int node, int poz, int val) {
if (st == dr) {
tree[node] = val;
return;
}
int mij = (st + dr) >> 1;
if (poz <= mij) {
update(st, mij, (node << 1), poz, val);
}
else {
update(mij + 1, dr, (node << 1) + 1, poz, val);
}
tree[node] = max(tree[(node << 1)], tree[(node << 1) + 1]);
}
int max_query(int st, int dr, int node, int a, int b) {
if (dr < a || st > b) {
return INT_MIN;
}
if (a <= st && dr <= b) {
return tree[node];
}
int mij = (st + dr) >> 1;
return max(max_query(st, mij, (node << 1), a, b),
max_query(mij + 1, dr, (node << 1) + 1, a, b));
}
int hld_query(int a, int b) {
int ans = INT_MIN;
while (head[a] != head[b]) {
if (niv[head[a]] < niv[head[b]]) {
swap(a, b);
}
ans = max(ans, max_query(1, n, 1, poz[head[a]], poz[a]));
a = par[head[a]];
}
if (niv[a] > niv[b]) {
swap(a, b);
}
ans = max(ans, max_query(1, n, 1, poz[a], poz[b]));
return ans;
}
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);
}
dfs(1, 0);
decompose(1, 1);
build_tree(1, n, 1);
while (q--) {
fin >> op >> x >> y;
if (op == 0) {
update(1, n, 1, poz[x], y);
}
else {
fout << hld_query(x, y) << '\n';
}
}
return 0;
}