#include <bits/stdc++.h>
using namespace std;
class InputReader
{
private:
static const int SIZE = 1 << 12;
char buf[SIZE]; int ptx;
FILE *inFile;
inline void advance (void)
{
if (++ptx == SIZE) {
ptx = 0; fread(buf, SIZE, 1, inFile); }
}
inline char current (void)
{
return buf[ptx];
}
public:
InputReader (const char *fileName)
{
inFile = fopen(fileName, "r"); ptx = 0;
fread(buf, SIZE, 1, inFile);
}
InputReader &operator >> (int &val)
{
val = 0;
while (current() < '0' || current() > '9') {
advance(); }
while (current() >= '0' && current() <= '9') {
val = val * 10 + (current() - '0');
advance(); }
return *this;
}
} in("heavypath.in");
ofstream out("heavypath.out");
const int DIM = 100005;
int szt[DIM], lev[DIM], wch[DIM], ftc[DIM], val[DIM];
int ord[DIM], fis[DIM], pos[DIM], sgt[DIM << 2];
vector<int> edg[DIM];
void dfs1 (int x, int f = 0)
{
static int nr = 0; int mx = -1;
szt[x] = 1; lev[x] = lev[f] + 1;
if (f) {
edg[x].erase(find(edg[x].begin(), edg[x].end(), f)); }
for (int y : edg[x]) {
dfs1(y, x); szt[x] += szt[y];
mx = max(mx, szt[y]); }
for (int it = 0; it < edg[x].size(); ++it) {
int y = edg[x][it];
if (szt[y] == mx) {
swap(edg[x][0], edg[x][it]); break; } }
if (mx == -1) {
wch[x] = ++nr; }
else {
wch[x] = wch[edg[x][0]];
for (int y : edg[x]) {
if (wch[y] != wch[x]) {
ftc[wch[y]] = x; } } }
}
void dfs2 (int x)
{
static int nr = 0;
ord[++nr] = x; pos[x] = nr;
for (int y : edg[x]) {
dfs2(y); }
}
void build (int nd, int le, int ri)
{
if (le == ri) {
sgt[nd] = val[ord[le]]; }
else {
int md = (le + ri) >> 1;
build(nd << 1, le, md);
build(nd << 1 | 1, md + 1, ri);
sgt[nd] = max(sgt[nd << 1], sgt[nd << 1 | 1]); }
}
void update (int nd, int le, int ri, int ps, int vl)
{
if (le == ri) {
sgt[nd] = vl; }
else {
int md = (le + ri) >> 1;
if (ps <= md) {
update(nd << 1, le, md, ps, vl); }
else {
update(nd << 1 | 1, md + 1, ri, ps, vl); }
sgt[nd] = max(sgt[nd << 1], sgt[nd << 1 | 1]); }
}
int query (int nd, int le, int ri, int st, int en)
{
if (st == le && en == ri) {
return sgt[nd]; }
else {
int md = (le + ri) >> 1;
if (en <= md) {
return query(nd << 1, le, md, st, en); }
else if (md < st) {
return query(nd << 1 | 1, md + 1, ri, st, en); }
else {
return max(query(nd << 1, le, md, st, md),
query(nd << 1 | 1, md + 1, ri, md + 1, en)); } }
}
int query_heavy (int x, int y, int n)
{
if (wch[x] == wch[y]) {
if (pos[x] > pos[y]) {
swap(x, y); }
return query(1, 1, n, pos[x], pos[y]); }
else {
if (lev[ftc[wch[x]]] > lev[ftc[wch[y]]]) {
swap(x, y); }
return max(query(1, 1, n, fis[wch[y]], pos[y]),
query_heavy(x, ftc[wch[y]], n)); }
}
int main (void)
{
int n, q; in >> n >> q;
for (int i = 1; i <= n; ++i) {
in >> val[i]; }
for (int i = 1; i < n; ++i) {
int x, y; in >> x >> y;
edg[x].push_back(y);
edg[y].push_back(x); }
dfs1(1); dfs2(1);
for (int i = 1; i <= n; ++i) {
int x = ord[i - 1], y = ord[i];
if (wch[x] != wch[y]) {
fis[wch[y]] = i; } }
build(1, 1, n);
while (q--) {
int t, x, y; in >> t >> x >> y;
if (t == 0) {
update(1, 1, n, pos[x], y); }
else {
out << query_heavy(x, y, n) << "\n"; } }
return 0;
}