#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#define MAXN 100000
#define LOG 20
std::vector <int> G[MAXN+1];
std::vector <int> L[LOG+1];
int father[MAXN+1],val[MAXN+1];
int lant[MAXN+1];
int dp[MAXN+1];
int poz[MAXN+1];
int lvl[MAXN+1];
std::vector <int> aint[LOG];
inline void add_Edge(int a,int b){
G[a].push_back(b);
}
int con;
void DFS1(int nod){
int i,maxim,nr;
if(G[nod].size()==0){
++con;
lant[nod]=con;
dp[nod]=1;
}
else{
maxim=0;
for(i=0;i<G[nod].size();i++){
DFS1(G[nod][i]);
if(dp[G[nod][i]]>maxim){
maxim=dp[G[nod][i]];
nr=lant[G[nod][i]];
}
}
dp[nod]=maxim+1;
lant[nod]=nr;
}
}
void DFS2(int nod){
int i;
L[lant[nod]].push_back(nod);
poz[nod]=L[lant[nod]].size()-1;
for(i=0;i<G[nod].size();i++){
lvl[G[nod][i]]=lvl[nod]+1;
DFS2(G[nod][i]);
}
}
inline int getmax(int a,int b){
if(a<b) return b;
return a;
}
inline int getmin(int a,int b){
if(a<b) return a;
return b;
}
void update(int nod,int left,int right,int poz,int val,int nr){
if(left==right)
aint[nr][nod]=val;
else{
int med=(left+right)/2;
if(poz<=med)
update(2*nod,left,med,poz,val,nr);
else
update(2*nod+1,med+1,right,poz,val,nr);
aint[nr][nod]=getmax(aint[nr][2*nod],aint[nr][2*nod+1]);
}
}
int max;
void query(int nod,int left,int right,int l,int r,int nr){
if(l<=left&&right<=r){
if(max<aint[nr][nod])
max=aint[nr][nod];
}
else{
int med=(left+right)/2;
if(l<=med)
query(2*nod,left,med,l,r,nr);
if(med<r)
query(2*nod+1,med+1,right,l,r,nr);
}
}
int main(){
FILE*fi,*fout;
int i,n,m,a,b,root,t,x,y,ans,aux,j;
fi=fopen("heavypath.in" ,"r");
fout=fopen("heavypath.out" ,"w");
fscanf(fi,"%d %d " ,&n,&m);
for(i=1;i<=n;i++)
fscanf(fi,"%d " ,&val[i]);
for(i=1;i<n;i++){
fscanf(fi,"%d %d " ,&a,&b);
add_Edge(a,b);
father[b]=a;
}
i=1;
while(father[i]>0)
i++;
root=i;
con=0;
DFS1(root);
for(i=0;i<=con;i++)
L[i].push_back(0);
lvl[root]=1;
DFS2(root);
for(i=1;i<=con;i++)
for(j=0;j<=4*L[i].size();j++)
aint[i].push_back(0);
for(i=1;i<=n;i++)
update(1,1,L[lant[i]].size()-1,poz[i],val[i],lant[i]);
while(m>0){
m--;
fscanf(fi,"%d %d %d " ,&t,&x,&y);
if(t==0)
update(1,1,L[lant[x]].size()-1,poz[x],y,lant[x]);
else{
ans=0;
while(lant[x]!=lant[y]){
if(lvl[L[lant[x]][1]]<lvl[L[lant[y]][1]]){
aux=x;
x=y;
y=aux;
}
max=0;
query(1,1,L[lant[x]].size()-1,1,poz[x],lant[x]);
if(max>ans)
ans=max;
x=father[L[lant[x]][1]];
}
max=0;
query(1,1,L[lant[x]].size()-1,getmin(poz[x],poz[y]),getmax(poz[x],poz[y]),lant[x]);
if(max>ans)
ans=max;
fprintf(fout,"%d\n" ,ans);
}
}
fclose(fi);
fclose(fout);
return 0;
}