#include <bits/stdc++.h>
using namespace std;
ifstream r("heavypath.in");
ofstream w("heavypath.out");
int n, i, j, nr, m, np, x, y, op, k, sol, mx, pu, val, a, b, ex, rez;
int ct[100002], v[100002], tt[100002], pth[100002], pos[100002], ext[100002], he[100002], ai[400002], st[100002];
vector<int> ad[100002];
void dfs_cate(int n)
{
ct[n]=1;
for(int i:ad[n]){
if(!ct[i])
{
dfs_cate(i);
ct[n]+=ct[i];
}
}
}
void make_paths(int n,int t,int h,int nw)
{
st[++ex]=n;
if(nw) {
np++;
pos[n]=1;
pth[n]=np;
ext[n]=ex-1;
tt[n]=t;
he[n]=h-1;
}
else {
pos[n]=pos[t]+1;
pth[n]=pth[t];
ext[n]=ext[t];
he[n]=he[t];
tt[n]=tt[t];
}
if(ad[n].size()==1 && n!=1){
return;
}
int ki=0;
for(int i:ad[n]){
if(ct[i]<ct[n] && ct[i]>ct[ki]){
ki=i;
}
}
make_paths(ki, n, h+1, 0);
for(int i:ad[n]){
if(ct[i]<ct[n] && i!=ki){
make_paths(i, n, h+1, 1);
}
}
}
void build(int n,int l,int r)
{
if(l==r)
{
ai[n]=v[st[++k]];
return;
}
int m=(l+r)/2;
build(2*n,l,m);
build(2*n+1,m+1,r);
ai[n]=max(ai[2*n],ai[2*n+1]);
}
void true_query(int n,int l,int r)
{
if(a<=l && r<=b)
{
rez=max(rez, ai[n]);
return;
}
int m=(l+r)/2;
if(a<=m){
true_query(2*n,l,m);
}
if(b>m){
true_query(2*n+1,m+1,r);
}
}
int query(int a,int b)
{
rez=0;
::a=a;
::b=b;
true_query(1,1,n);
return rez;
}
void true_update(int n,int l,int r)
{
if(l==r)
{
ai[n]=b;
return;
}
int m=(l+r)/2;
if(a<=m){
true_update(2*n,l,m);
}
else{
true_update(2*n+1,m+1,r);
}
ai[n]=max(ai[2*n],ai[2*n+1]);
}
void update(int pos,int val)
{
a=pos;
b=val;
true_update(1,1,n);
}
int main() {
r>>n>>m;
for(i=1;i<=n;i++){
r>>v[i];
}
for(i=1;i<n;i++)
{
r>>x>>y;
ad[x].push_back(y);
ad[y].push_back(x);
}
dfs_cate(1);
make_paths(1,0,1,1);
k=0;
build(1,1,n);
while(m--)
{
r>>op>>x>>y;
if(op==0){
update(ext[x]+pos[x], y);
}
else
{
sol=0;
while(1)
{
if(pth[x]==pth[y])
{
sol=max(sol, query(ext[x]+min(pos[x],pos[y]), ext[x]+max(pos[x],pos[y])));
break;
}
if(he[x]<he[y]){
k=x;
x=y;
y=k;
}
sol=max(sol, query(ext[x]+1,ext[x]+pos[x]));
x=tt[x];
}
w<<sol<<"\n";
}
}
}