#include <bits/stdc++.h>
using namespace std;
FILE *fin = fopen ("heavypath.in", "r"), *fout = fopen ("heavypath.out", "w");
const int MAXN = 1e5;
int s[MAXN + 1], dad[MAXN + 1], level[MAXN + 1], link[MAXN + 1], poz[MAXN + 1], v[MAXN + 1];
int seg[4 * MAXN + 1];
vector <int> gr[MAXN + 1];
int cnt;
int n;
int dfs (int nod, int tata) {
s[nod] = 1;
dad[nod] = tata;
if (tata == -1)
level[nod] = 1;
else
level[nod] = level[tata] + 1;
for (auto fiu : gr[nod])
if (fiu != tata)
s[nod] += dfs (fiu, nod);
return s[nod];
}
void make_links (int nod, int tata) {
int mx;
poz[nod] = ++cnt;
mx = 0;
for (auto fiu : gr[nod])
if (fiu != tata && s[fiu] > s[mx])
mx = fiu;
if (mx) {
link[mx] = link[nod];
make_links (mx, nod);
}
for (auto fiu : gr[nod])
if (fiu != tata && mx != fiu) {
link[fiu] = fiu;
make_links (fiu, nod);
}
}
void update (int poz, int val) {
poz += n;
seg[poz] = val;
poz = poz / 2;
while (poz > 1) {
seg[poz] = max (seg[2 * poz], seg[2 * poz + 1]);
poz = poz / 2;
}
}
int query (int st, int dr) {
int sol = 0;
st += n;
dr += n + 1;
while (st != dr) {
if (st % 2)
sol = max (sol, seg[st++]);
if (dr % 2)
sol = max (sol, seg[--dr]);
st = st / 2;
dr = dr / 2;
}
return sol;
}
int main() {
int m, i, x, y, t, a, b, sol;
fscanf (fin, "%d%d", &n, &m);
for (i = 1; i <= n; i++)
fscanf (fin, "%d", &v[i]);
for (i = 1; i < n; i++) {
fscanf (fin, "%d%d", &x, &y);
gr[x].push_back (y);
gr[y].push_back (x);
}
dfs (1, -1);
link[1] = 1;
cnt = 0;
make_links (1, -1);
for (i = 1; i <= n; i++)
update (poz[i], v[i]);
while (m--) {
fscanf (fin, "%d%d%d", &t, &a, &b);
if (t == 0)
update (poz[a], b);
else {
sol = 0;
while (link[a] != link[b]) {
if (level[link[a]] < level[link[b]])
swap(a, b);
sol = max (sol, query (poz[link[a]], poz[a]));
a = dad[link[a]];
}
if (level[a] < level[b])
swap (a, b);
sol = max (sol, query (poz[b], poz[a]));
fprintf (fout, "%d\n", sol);
}
}
fclose (fin);
fclose (fout);
return 0;
}