#include <bits/stdc++.h>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
const int N_MAX = 1e5;
const int Q_MAX = 1e5;
struct defST {
int DS[1 + 4 * N_MAX];
void update (int node, int left, int right, int pos, int x) {
if (left == right) DS[node] = x;
else {
int mid = left + (right - left) / 2;
if (pos <= mid) update (2 * node, left, mid, pos, x);
else update (2 * node + 1, mid + 1, right, pos, x);
DS[node] = max (DS[2 * node], DS[2 * node + 1]);
}
}
int query (int node, int left, int right, int qleft, int qright) {
if (qleft <= left && right <= qright) return DS[node];
int mid = left + (right - left) / 2;
int ret = 0;
if (qleft <= mid) ret = max (ret, query (2 * node, left, mid, qleft, qright));
if (mid + 1 <= qright) ret = max (ret, query (2 * node + 1, mid + 1, right, qleft, qright));
return ret;
}
} ST;
int N, Q; int values[1 + N_MAX];
vector<int> tree[1 + N_MAX];
void readInput (void) {
fin >> N >> Q;
for (int node = 1; node <= N; node ++) fin >> values[node];
for (int i = 1; i < N; i ++) {
int u, v; fin >> u >> v;
tree[u].push_back (v);
tree[v].push_back (u);
}
}
struct defNode {
int p, siz, depth;
int pos, head;
} infos[1 + N_MAX];
void dfs (int root, int p) {
infos[root].p = p;
infos[root].depth = infos[p].depth + 1;
infos[root].siz = 1;
for (int node : tree[root]) {
if (node == p) continue;
dfs (node, root);
infos[root].siz += infos[node].siz;
}
}
int T = 0;
void dfsHeavy (int root, int p, int head) {
infos[root].pos = ++ T;
infos[root].head = head;
int hc = 0;
for (int node : tree[root]) {
if (node == p) continue;
if (infos[hc].siz < infos[node].siz)
hc = node;
}
if (hc > 0) dfsHeavy (hc, root, head);
for (int node : tree[root]) {
if (node == p || node == hc) continue;
dfsHeavy (node, root, node);
}
}
void update (int node, int new_value) {
ST.update (1, 1, N, infos[node].pos, new_value);
}
int query (int u, int v) {
int ret = 0;
while (infos[u].head != infos[v].head) {
int hu = infos[u].head, hv = infos[v].head;
if (infos[hu].depth > infos[hv].depth) {
swap (u, v);
swap (hu, hv);
}
ret = max (ret, ST.query (1, 1, N, infos[hv].pos, infos[v].pos));
v = infos[hv].p;
}
if (infos[u].depth > infos[v].depth) swap (u, v);
ret = max (ret, ST.query (1, 1, N, infos[u].pos, infos[v].pos));
return ret;
}
int main () {
readInput ();
dfs (1, 0);
dfsHeavy (1, 0, 1);
for (int node = 1; node <= N; node ++) ST.update (1, 1, N, infos[node].pos, values[node]);
for (int i = 1; i <= Q; i ++) {
int t, x, y; fin >> t >> x >> y;
if (t == 0) update (x, y);
else fout << query (x, y) << "\n";
}
return 0;
}