#include<bits/stdc++.h>
using namespace std;
const int maxN=(1e5)+5;
int A[4*maxN+5];
int val[maxN];
vector<int> v[maxN],ch[maxN];
void build(int nod,int st,int dr,int offset,int i)
{
if(st==dr)
{
A[offset+nod]=val[ch[i][st-1]];
return;
}
int mid=(st+dr)>>1;
build(2*nod,st,mid,offset,i);
build(2*nod+1,mid+1,dr,offset,i);
A[offset+nod]=max(A[offset+2*nod],A[offset+2*nod+1]);
}
int where[maxN],pos[maxN];
void update(int nod,int st,int dr,int pos,int offset,int i)
{
if(st==dr)
{
A[offset+nod]=val[ch[i][st-1]];
return;
}
int mid=(st+dr)>>1;
if(pos<=mid) update(2*nod,st,mid,pos,offset,i);
else update(2*nod+1,mid+1,dr,pos,offset,i);
A[offset+nod]=max(A[offset+2*nod],A[offset+2*nod+1]);
}
int chains,w[maxN],t[maxN],T[maxN],lvl[maxN];
int sz[maxN];
bool cmp(int x,int y)
{
return lvl[x]<lvl[y];
}
inline int query(int nod,int st,int dr,int a,int b,int offset)
{
if(a<=st && dr<=b)
{
return A[offset+nod];
}
int mid=(st+dr)>>1;
int q=0;
if(a<=mid) q=max(q,query(2*nod,st,mid,a,b,offset));
if(b>mid) q=max(q,query(2*nod+1,mid+1,dr,a,b,offset));
return q;
}
void dfs(int nod,int fat)
{
w[nod]=1;
int best=0;
lvl[nod]=1+lvl[fat];
t[nod]=fat;
for(auto it:v[nod])
{
if(it==fat) continue;
dfs(it,nod);
w[nod]+=w[it];
if(w[it]>w[best]) best=it;
}
if(w[nod]==1) //frunza, vom face lant nou
{
chains++;
where[nod]=chains;
ch[where[nod]].push_back(nod);
T[chains]=fat;
sz[chains]=1;
pos[nod]=sz[chains];
}
else
{
where[nod]=where[best];
ch[where[nod]].push_back(nod);
sz[where[nod]]++;
pos[nod]=sz[where[nod]];
}
}
int n,q,x,y;
int offset[maxN];
int op;
int main()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
for(int i=1;i<=chains;i++)
{
sort(ch[i].begin(),ch[i].end(),cmp);
T[i]=t[ch[i][0]];
for(int j=0;j<(int)ch[i].size();j++)
pos[ch[i][j]]=j+1;
}
//
for(int i=1;i<=chains;i++)
offset[i]=offset[i-1]+4*sz[i];
for(int i=1;i<=chains;i++)
build(1,1,sz[i],offset[i-1],i);
// cerr<<ch[1][2]<<'\n';
while(q--)
{
scanf("%d%d%d",&op,&x,&y);
if(!op)
{
val[x]=y;
int wx=where[x];
update(1,1,sz[where[x]],pos[x],offset[wx-1],wx);
}
else
{
int wx=where[x];
int wy=where[y];
int sol=0;
do
{
if(wx!=wy)
{
if(lvl[T[wx]]>lvl[T[wy]])
{
sol=max(sol,query(1,1,sz[wx],1,pos[x],offset[wx-1]));
x=T[wx];
wx=where[x];
}
else
{
sol=max(sol,query(1,1,sz[wy],1,pos[y],offset[wy-1]));
y=T[wy];
wy=where[y];
}
}
if(wx==wy)
{
if(pos[x]>pos[y]) swap(x,y);
sol=max(sol,query(1,1,sz[wx],pos[x],pos[y],offset[wx-1]));
}
}while(wx!=wy);
printf("%d\n",sol);
}
}
return 0;
}