#include<fstream>
#include<algorithm>
#include<vector>
using namespace std;
ifstream f("heavypath.in");
ofstream o("heavypath.out");
vector <int> a[100100],b[100100];
int v[100100],n,m,k=0,path[100010],l[100100],tata[100100],idpath[1000100],def[1000100],arb[4000000],idar[100100],parc[100100];
void df(int nod,int v){
l[nod] = v;
if(a[nod].size()==1 && nod!=1){
k++;
b[k].push_back(nod);
path[nod]=k;
idpath[k]=v;
idar[nod]=0;
return;
}
parc[nod]=1;
int maxim = -1;
for(int i=0;i<a[nod].size();i++)
if(parc[a[nod][i]]!=1){
df(a[nod][i],v+1);
if(maxim==-1)maxim=a[nod][i];
else{
if(idpath[path[a[nod][i]]]==idpath[path[maxim]]){
if(path[a[nod][i]]<path[maxim])maxim=a[nod][i];
}else{
if(idpath[path[a[nod][i]]]>idpath[path[maxim]])maxim=a[nod][i];
}
}
tata[path[a[nod][i]]]=nod;
}
path[nod] = path[maxim];
b[path[maxim]].push_back(nod);
idar[nod] = b[path[maxim]].size()-1;
tata[path[maxim]]=0;
parc[nod]=0;
}
void init(int x,int d,int l,int r,int nod=1){
if(r==l){
arb[d+nod]=v[b[x][l]];
return;
}
int m=(l+r)/2;
init(x,d,l,m,nod*2);
init(x,d,m+1,r,nod*2+1);
arb[d+nod] = max(arb[d+nod*2+1],arb[d+nod*2]);
}
void make_tree(){
int d=0;
for(int i=1;i<=k;i++){
def[i]=d;
d+=(b[i].size())*4+1;
init(i,def[i],0,b[i].size()-1);
}
}
void update(int x,int val,int i,int l,int r,int d,int nod){
if(l==r){
arb[nod+d] = val;
return;
}
int m = (l+r)/2;
if(x<=m)update(x,val,i,l,m,d,nod*2);
else update(x,val,i,m+1,r,d,nod*2+1);
arb[d+nod] = max(arb[d+nod*2+1],arb[d+nod*2]);
}
int query(int q,int p,int d,int l,int r,int nod){
if(q<=l && p>=r)return arb[nod+d];
int m = (l+r)/2,rs=-1;
if(m>=q)rs = query(q,p,d,l,m,nod*2);
if(m+1<=p)rs = max(rs,query(q,p,d,m+1,r,nod*2+1));
return rs;
}
int lca(int x,int y){
if(idpath[path[x]]==idpath[path[y]]){
if(path[x]<path[y])swap(x,y);
}else if(idpath[path[x]]>idpath[path[y]])swap(x,y);//x e mai jos ca y in arbore
// o<<x<<" "<<y<<endl;
int stop=1,rs=-1;
while(stop){
if(path[x]==path[y]){
stop=0;
if(l[x]<l[y])swap(x,y);//x e mai jos ca y in arbore
rs = max(rs,query(idar[x],idar[y],def[path[x]],0,b[path[x]].size()-1,1));
// o<<x<<" "<<y<<endl;
}else{
rs = max(rs,query(idar[x],idar[b[path[x]][b[path[x]].size()-1]],def[path[x]],0,b[path[x]].size()-1,1));
x = tata[path[x]];
// o<<x<<" "<<y<<endl;
if(idpath[path[x]]==idpath[path[y]]){
if(path[x]<path[y])swap(x,y);
}else if(idpath[path[x]]>idpath[path[y]])swap(x,y);
}
}
// o<<endl;
return rs;
}
int main(){
f>>n>>m;
for(int i=1;i<=n;i++)f>>v[i];
int x,y,z;
for(int i=1;i<n;i++){
f>>x>>y;
a[x].push_back(y);
a[y].push_back(x);
}
df(1,1);
make_tree();
/*
for(int i=1;i<=k;i++){
o<<i<<" "<<def[i]<<" "<<tata[i]<<" "<<idpath[i]<<endl;
for(int j=0;j<b[i].size();j++)o<<b[i][j]<<" ";
o<<endl;
}
for(int i=1;i<=n;i++)o<<path[i]<<" ";o<<endl;
for(int i=1;i<=n;i++)o<<idar[i]<<" ";o<<endl;
for(int i=1;i<=n;i++)o<<l[i]<<" ";o<<endl;
for(int i=1;i<=4*n;i++)o<<arb[i]<<" ";o<<endl;*/
//return 0;
for(int i=1;i<=m;i++){
f>>x;
if(x){
f>>z>>y;
o<<lca(z,y)<<"\n";
}else{
f>>z>>y;
update(idar[z],y,path[z],0,b[path[z]].size()-1,def[path[z]],1);
// for(int i=1;i<=4*n;i++)o<<arb[i]<<" ";o<<endl;
}
}
}