#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector <int> vec[100005];
int n,m;
int v[100005];
int tata[100005],depth[100005];
int cap[100005],vals[100005],desc[100005];
int heavy[100005];
int aint[400005];
int dfs(int nod,int par)
{
int cursize=1;
int maxval=-1;
for(auto x:vec[nod])
if(x!=par)
{
tata[x]=nod;
depth[x]=depth[nod]+1;
int newval=dfs(x,nod);
cursize+=newval;
if(newval>maxval)
{
maxval=newval;
heavy[nod]=x;
}
}
return cursize;
}
int poz;
void hld(int head,int nod)
{
vals[nod]=++poz;
cap[nod]=head;
if(heavy[nod])
hld(head,heavy[nod]);
for(auto x:vec[nod])
{
if(x!=heavy[nod]&&x!=tata[nod])
hld(x,x);
}
}
void build(int nod,int st,int dr)
{
if(st==dr)
{
aint[nod]=desc[st];
}
else
{
int mid=(st+dr)/2;
build(2*nod,st,mid);
build(2*nod+1,mid+1,dr);
aint[nod]=max(aint[2*nod],aint[2*nod+1]);
}
}
void update(int nod,int st,int dr,int poz,int val)
{
if(st==dr)
{
aint[nod]=val;
}
else
{
int mid=(st+dr)/2;
if(poz<=mid)
update(2*nod,st,mid,poz,val);
else
update(2*nod+1,mid+1,dr,poz,val);
aint[nod]=max(aint[2*nod],aint[2*nod+1]);
}
}
int aintquery(int nod,int st,int dr,int ql,int qr)
{
if(ql>qr)
return 0;
if(st==ql&&dr==qr)
return aint[nod];
else
{
int mid=(st+dr)/2;
return max(aintquery(2*nod,st,mid,ql,min(mid,qr)),aintquery(2*nod+1,mid+1,dr,max(ql,mid+1),qr));
}
}
int query(int x,int y)
{
int ans=0;
while(cap[x]!=cap[y])
{
if(depth[cap[x]]>depth[cap[y]])
swap(x,y);
ans=max(ans,aintquery(1,1,n,vals[cap[y]],vals[y]));
y=tata[cap[y]];
}
if(vals[x]>vals[y])
swap(x,y);
ans=max(ans,aintquery(1,1,n,vals[x],vals[y]));
return ans;
}
int main()
{
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>v[i];
for(int i=1;i<n;i++)
{
int x,y;
fin>>x>>y;
vec[x].push_back(y);
vec[y].push_back(x);
}
dfs(1,0);
hld(1,1);
for(int i=1;i<=n;i++)
{
desc[vals[i]]=v[i];
}
build(1,1,n);
for(int i=1;i<=m;i++)
{
int t,x,y;
fin>>t>>x>>y;
if(t==0)
{
update(1,1,n,vals[x],y);
desc[vals[x]]=y;
/*for(int j=1;j<=n;j++)
fout<<desc[j]<<' ';
fout<<'\n';*/
}
if(t==1)
{
fout<<query(x,y)<<'\n';
}
}
return 0;
}