#include <iostream>
#include <vector>
using namespace std;
#define NMAX 100005
#define def int nod=1, int st=1, int dr=n
#define int size_t
int n, q, x, y, val, sum=0, cp=0;
int sz[NMAX], hchild[NMAX], d[NMAX], aint[4*NMAX], a[NMAX], pr[NMAX], head[NMAX], pos[NMAX];
vector<int> g[NMAX];
void dfs(int r, int p){
++sz[r];
pr[r]=p;
int maxim=0;
hchild[r]=-1;
for (auto it:g[r]){
if (it==p)continue;
d[it]=d[r]+1;
dfs(it, r);
sz[r]+=sz[it];
if (maxim<sz[it]){
maxim=sz[it];
hchild[r]=it;
}
}
}
void update(def){
if (st==dr){
aint[nod]=val;
return;
}
int mij=(st+dr)/2;
if (x<=mij)update(2*nod, st, mij);
else update(2*nod+1, mij+1, dr);
aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}
void query(def){
if (y<st || dr<x)return;
if (x<=st && dr<=y){
sum=max(sum, aint[nod]);
return;
}
int mij=(st+dr)/2;
query(2*nod, st, mij);
query(2*nod+1, mij+1, dr);
}
void dec_dfs(int r, int p, int h){
head[r]=h;
pos[r]=cp++;
x=pos[r], val=a[r];
update();
if (hchild[r]!=-1){
dec_dfs(hchild[r], r, h);
}
for (auto it:g[r]){
if (it==p || it==hchild[r])continue;
dec_dfs(it, r, it);
}
}
void path_query(){
int i=x, j=y;
while (head[i]!=head[j]){
if (d[head[i]]>d[head[j]])swap(i, j);
x=pos[head[j]], y=pos[j];
query();
j=pr[head[j]];
}
if (d[i]>d[j])swap(i, j);
x=pos[i], y=pos[j];
query();
}
void solve(){
cin>>n>>q;
for (int i=1; i<=n; ++i)cin>>a[i];
for (int i=1; i<n; ++i){
int x, y;
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1, 0);
dec_dfs(1, 0, 1);
for (int i=0; i<q; ++i){
int op;
cin>>op;
if (op==0){
// update
cin>>x>>val;
x=pos[x];
update();
} else {
// query
cin>>x>>y;
sum=0;
path_query();
cout<<sum<<"\n";
}
}
}
signed main(){
#ifdef LOCAL
freopen("date.in", "r", stdin);
freopen("date.out", "w", stdout);
#else
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
#endif
solve();
return 0;
}