#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int i,j,x11,y11,Q,p1,p2,sol,X,Y,m,n,tip,nod,val,PP[100009],Path[100009],t[100009],T[100009],niv[100009],Nr[100009],ap[100009],a[100009];
vector < int > muc[100009],V[100009],Aint[100009];
void dfs(int nod)
{
vector < int > :: iterator it;
ap[nod]=Nr[nod]=1;
int pz=-1;
for(it=muc[nod].begin();it!=muc[nod].end();it++)
if(ap[*it]==0)
{
dfs(*it);
t[*it]=nod;
Nr[nod]+=Nr[*it];
if(pz==-1||Nr[*it]>Nr[pz]) pz=*it;
}
if(pz==-1) Path[nod]=++Q;
else Path[nod]=Path[pz];
V[Path[nod]].push_back(nod);
}
void dfs2(int nod)
{
vector < int > :: iterator it;
for(it=muc[nod].begin();it!=muc[nod].end();it++)
if(*it!=t[nod])
{
if(Path[nod]!=Path[*it]) niv[Path[*it]]=niv[Path[nod]]+1;
dfs2(*it);
}
}
void Build(int lv,int nod,int st,int dr)
{
if(st==dr)
{
Aint[lv][nod]=a[V[lv][st-1]];
return ;
}
int mij=(st+dr)>>1;
Build(lv,nod<<1,st,mij);
Build(lv,(nod<<1)+1,mij+1,dr);
Aint[lv][nod]=max(Aint[lv][nod<<1],Aint[lv][(nod<<1)+1]);
}
void Update(int lv,int nod,int st,int dr,int poz,int val)
{
if(st==dr)
{
Aint[lv][nod]=val;
return ;
}
int mij=(st+dr)>>1;
if(poz<=mij) Update(lv,nod<<1,st,mij,poz,val);
else Update(lv,(nod<<1)+1,mij+1,dr,poz,val);
Aint[lv][nod]=max(Aint[lv][nod<<1],Aint[lv][(nod<<1)+1]);
}
int Query(int lv,int nod,int st,int dr,int x,int y)
{
if(x<=st&&dr<=y) return Aint[lv][nod];
int mij=(st+dr)>>1,maxi=0;
if(x<=mij) maxi=Query(lv,nod<<1,st,mij,x,y);
if(y>mij) maxi=max(maxi,Query(lv,(nod<<1)+1,mij+1,dr,x,y));
return maxi;
}
int main()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
scanf("%d",&n);
scanf("%d",&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<n;i++)
{
scanf("%d",&x11);
scanf("%d",&y11);
muc[x11].push_back(y11);
muc[y11].push_back(x11);
}
dfs(1);
for(i=1;i<=Q;i++)
{
reverse(V[i].begin(),V[i].end());
for(j=0;j<V[i].size();j++)
PP[V[i][j]]=j+1;
Aint[i].resize(V[i].size()*4);
Build(i,1,1,V[i].size());
}
dfs2(1);
for(i=2;i<=n;i++)
if(Path[t[i]]!=Path[i])
T[Path[i]]=t[i];
while(m)
{
m--;
scanf("%d",&tip);
if(tip==0)
{
scanf("%d",&nod);
scanf("%d",&val);
Update(Path[nod],1,1,V[Path[nod]].size(),PP[nod],val);
}
else
{
scanf("%d",&X);
scanf("%d",&Y);
sol=0;
p1=Path[X];
p2=Path[Y];
sol=0;
while(p1!=p2)
{
if(niv[p1]<niv[p2])
{
sol=max(sol,Query(p2,1,1,V[p2].size(),1,PP[Y]));
Y=T[p2];
p2=Path[T[p2]];
}
else
{
sol=max(sol,Query(p1,1,1,V[p1].size(),1,PP[X]));
X=T[p1];
p1=Path[T[p1]];
}
}
if(PP[X]<PP[Y]) sol=max(sol,Query(p1,1,1,V[p1].size(),PP[X],PP[Y]));
else sol=max(sol,Query(p1,1,1,V[p1].size(),PP[Y],PP[X]));
printf("%d\n",sol);
}
}
return 0;
}