#include <bits/stdc++.h>
using namespace std;
const int SPQR = 100005; // Ave Imperator, morituri te salutant!
int cbuff;
int lvl[SPQR], w[SPQR], lch[SPQR], far[SPQR], pos[SPQR], v[SPQR];
vector<int> g[SPQR], chn[SPQR], barn[SPQR], spom[SPQR];
void dfs(int u) {
w[u] = 1;
for(auto i: g[u]) if(!lvl[i]) {
lvl[i] = lvl[u] + 1;
far[i] = u;
barn[u].push_back(i);
dfs(i);
w[u]+= w[i]; } }
void rupeti_lanturile(int u) {
int maxw, maxi;
chn[cbuff].push_back(u);
pos[u] = chn[cbuff].size() - 1;
lch[u] = cbuff;
maxw = -1;
for(auto i: barn[u]) {
if(w[i] > maxw) {
maxw = w[i];
maxi = i; } }
if(maxw > 0) rupeti_lanturile(maxi);
for(auto i: barn[u]) if(i != maxi) {
chn[++cbuff].push_back(0);
rupeti_lanturile(i); } }
void make_pom(int cidx, int nod, int st, int dr) {
if(st==dr) {
spom[cidx][nod] = v[chn[cidx][st]];
return; }
int m = (st + dr) / 2;
make_pom(cidx, 2 * nod, st, m);
make_pom(cidx, 2 * nod + 1, m + 1, dr);
spom[cidx][nod] = max(spom[cidx][2 * nod], spom[cidx][2 * nod + 1]); }
void traiasca_regele(void) {
for(int i=1; i<=cbuff; ++i) {
spom[i].resize(4 * chn[i].size() + 5);
make_pom(i, 1, 1, chn[i].size() - 1); } }
int query(int cidx, int nod, int st, int dr, int x, int y) {
if(x<=st && dr<=y) {
return spom[cidx][nod]; }
int r, m;
m = (st + dr) / 2;
r = 0;
if(x<=m) r = max(r, query(cidx, 2 * nod, st, m, x, y));
if(y>m) r = max(r, query(cidx, 2 * nod + 1, m + 1, dr, x, y));
return r; }
void update(int cidx, int nod, int st, int dr, int pos, int val) {
if(st == dr) {
v[st] = val;
spom[cidx][nod] = val;
return; }
int m = (st + dr) / 2;
if(pos <= m) update(cidx, 2 * nod, st, m, pos, val);
else update(cidx, 2 * nod + 1, m + 1, dr, pos, val);
spom[cidx][nod] = max(spom[cidx][2 * nod], spom[cidx][2 * nod + 1]); }
int get_max(int a, int b) {
if(lch[a] == lch[b]) {
if(pos[a] > pos[b])
return query(lch[a], 1, 1, chn[lch[a]].size()-1, pos[b], pos[a]);
else
return query(lch[a], 1, 1, chn[lch[a]].size()-1, pos[a], pos[b]); }
int lead_a, lead_b;
lead_a = chn[lch[a]][1];
lead_b = chn[lch[b]][1];
if(lvl[lead_a] > lvl[lead_b])
return max(query(lch[a], 1, 1, chn[lch[a]].size()-1, 1, pos[a]), get_max(far[lead_a], b));
else
return max(query(lch[b], 1, 1, chn[lch[b]].size()-1, 1, pos[b]), get_max(far[lead_b], a)); }
int main(void) {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int tip, n, m, x, y;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) {
scanf("%d", &v[i]); }
for(int i=1; i<n; ++i) {
scanf("%d%d", &x, &y);
g[x].push_back(y);
g[y].push_back(x); }
chn[1].push_back(0);
lvl[1] = 1;
cbuff = 1;
dfs(1);
rupeti_lanturile(1);
traiasca_regele();
while(m--) {
scanf("%d%d%d", &tip, &x, &y);
switch(tip) {
case 0: {
update(lch[x], 1, 1, chn[lch[x]].size()-1, pos[x], y);
break; }
case 1: {
printf("%d\n", get_max(x, y));
break; } } }
return 0; }