#include <bits/stdc++.h>
using namespace std;
ifstream in ("heavypath.in");
ofstream out ("heavypath.out");
using int64 = long long;
const int N_MAX = 1e5;
const int Q_MAX = 1e5;
struct defNode {
int value;
int siz, depth, p;
int heavyChild, pos, head; /// poz = pozitia in HLD
} infos[1 + N_MAX];
int N, Q;
vector<int> tree[1 + N_MAX];
void readInput (void) {
in >> N >> Q;
for (int node = 1; node <= N; node ++) in >> infos[node].value;
for (int i = 1; i < N; i ++) {
int a, b; in >> a >> b;
tree[a].push_back (b);
tree[b].push_back (a);
}
}
void init_dfs (int root, int p) {
infos[root].siz = 1;
infos[root].depth = infos[p].depth + 1;
infos[root].p = p;
for (int node : tree[root]) {
if (node == p) continue;
init_dfs (node, root);
infos[root].siz += infos[node].siz;
}
}
void dfs_HLD (int root, int p, int currHead) {
infos[root].head = currHead;
int t = 0;
for (int node : tree[root]) {
if (node == p) continue;
if (infos[node].siz > infos[t].siz) t = node;
}
infos[root].heavyChild = t;
for (int node : tree[root]) {
if (node != p && node != infos[root].heavyChild)
dfs_HLD (node, root, node);
}
if (infos[root].heavyChild) dfs_HLD (infos[root].heavyChild, root, currHead);
}
int order[1 + N_MAX];
void construct_HLD (void) {
int pos = 0;
for (int node = 1; node <= N; node ++) {
if (infos[node].head == node) {
int aux = node;
while (aux) {
///cout << aux << " ";
order[++ pos] = aux;
infos[aux].pos = pos;
aux = infos[aux].heavyChild;
}
///cout << "\n";
}
}
}
int ST[1 + 4 * N_MAX];
void update (int node, int left, int right, int pos, int newValue) {
if (left == right)
ST[node] = newValue;
else {
int mid = left + (right - left) / 2;
if (pos <= mid) update (2 * node, left, mid, pos, newValue);
else update (2 * node + 1, mid + 1, right, pos, newValue);
ST[node] = max (ST[2 * node], ST[2 * node + 1]);
}
}
int query (int node, int left, int right, int qleft, int qright) {
if (qleft <= left && right <= qright) return ST[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;
}
int query_HLD (int a, int b) {
int answer = 0;
while (infos[a].head != infos[b].head) {
if (infos[infos[a].head].depth < infos[infos[b].head].depth) swap (a, b);
int start = infos[infos[a].head].pos;
answer = max (answer, query (1, 1, N, start, infos[a].pos));
a = infos[infos[a].head].p;
}
if (infos[a].pos > infos[b].pos) swap (a, b);
answer = max (answer, query (1, 1, N, infos[a].pos, infos[b].pos));
return answer;
}
int main()
{
readInput ();
init_dfs (1, 0);
dfs_HLD (1, 0, 1);
construct_HLD ();
for (int i = 1; i <= N; i ++) update (1, 1, N, i, infos[order[i]].value);
for (int i = 1; i <= Q; i ++) {
int t; in >> t;
if (t == 0) {
int node, x; in >> node >> x;
update (1, 1, N, infos[node].pos, x);
}
else {
int a, b; in >> a >> b;
out << query_HLD (a, b) << "\n";
}
}
return 0;
}