#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream si("heavypath.in");
ofstream so("heavypath.out");
const int MAXN=100005;
vector<int> v[MAXN],arb[MAXN];
int val[MAXN],s[MAXN],niv[MAXN],lant[MAXN],lp[MAXN],ls[MAXN],lt[MAXN],nlant;
void dfs(int nod,int tata,int lvl)
{
s[nod]=1;
niv[nod]=lvl;
vector<int>::iterator i;
for(i=v[nod].begin();i!=v[nod].end();++i)
if(*i!=tata)
{
dfs(*i,nod,lvl+1);
s[nod]+=s[*i];
}
}
void dfs1(int nod,int tata,int l)
{
lant[nod]=l;
++ls[l];
lp[nod]=ls[l];
int h=0;
vector<int>::iterator i;
for(i=v[nod].begin();i!=v[nod].end();++i)
{
if(*i!=tata&&s[*i]>s[h])
h=*i;
}
if(!h)
return;
dfs1(h,nod,l);
for(i=v[nod].begin();i!=v[nod].end();++i)
{
if(*i!=tata&&*i!=h)
{
++nlant;
lt[nlant]=nod;
dfs1(*i,nod,nlant);
}
}
}
void update(int nod,int st,int dr,int poz,int val,vector<int>&arb)
{
if(st==dr)
{
arb[nod]=val;
return;
}
int mid=(st+dr)>>1;
if(poz<=mid)
update(nod*2,st,mid,poz,val,arb);
else
update(nod*2+1,mid+1,dr,poz,val,arb);
arb[nod]=max(arb[nod*2],arb[nod*2+1]);
}
int query(int nod,int st,int dr,int qs,int qd,vector<int> &arb)
{
if(qs<=st&&qd>=dr)
return arb[nod];
int mid=(st+dr)/2,sol=0;
if(qs<=mid)
{
sol=max(sol,query(nod*2,st,mid,qs,qd,arb));
}
if(qd>mid)
{
sol=max(sol,query(nod*2+1,mid+1,dr,qs,qd,arb));
}
return sol;
}
int main()
{
int n,m,x,y,q;
si>>n>>m;
int i;
for(i=1;i<=n;i++)
si>>val[i];
for(i=1;i<n;++i)
{
si>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0,1);
//cout<<1;
nlant=1;
dfs1(1,0,nlant);
for(i=1;i<=nlant;++i)
arb[i].resize(ls[i]*4);
//cout<<1;
for(i=1;i<=n;++i)
{
update(1,1,ls[lant[i]],lp[i],val[i],arb[lant[i]]);
}
for(i=1;i<=m;++i)
{
si>>q>>x>>y;
if(q==0)
update(1,1,ls[lant[x]],lp[x],y,arb[lant[x]]);
else
{
int sol=0;
while(lant[x]!=lant[y])
{
if(niv[lt[lant[x]]]<niv[lt[lant[y]]])
swap(x,y);
sol=max(sol,query(1,1,ls[lant[x]],1,lp[x],arb[lant[x]]));
x=lt[lant[x]];
}
if(lp[x]>lp[y])
swap(x,y);
sol=max(sol,query(1,1,ls[lant[x]],lp[x],lp[y],arb[lant[x]]));
so<<sol<<'\n';
}
}
return 0;
}