#include<stdio.h>
#include<algorithm>
#include<vector>
#include<utility>
using namespace std;
#define maxq 100010
#define max(a,b) ((a)>(b) ? (a):(b))
int n,m,v[maxq],fol[maxq],niv[maxq],w[maxq],lD[maxq],l[maxq],nl,lDad[maxq],lNiv[maxq],lPoz[maxq];
int arb[4*maxq];
vector<int> G[maxq],P[maxq];
pair<int, pair<int,int> > Op[maxq];
void read()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&v[i]);
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
int a;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&x,&y);
Op[i]=make_pair(a,make_pair(x,y));
}
}
void df(int node)
{
fol[node]=1;
w[node]=1;
int a=-1,frunza=1;
for(vector<int>::iterator it=G[node].begin();it!=G[node].end();++it)
{
if(fol[*it])
continue;
frunza=0;
niv[*it]=niv[node]+1;
df(*it);
w[node]+=w[*it];
if(a==-1)
a=*it;
else
if(w[a]<w[*it])
a=*it;
}
if(frunza)
{
l[node] = ++nl;
lD[nl]=1;
P[nl].push_back(node);
return;
}
l[node]=l[a];
++lD[l[node]];
P[l[node]].push_back(node);
for(vector<int>::iterator it=G[node].begin();it!=G[node].end();it++)
{
if((*it)==a || niv[*it] < niv[node] )
continue;
lDad[l[*it]]=node;
lNiv[l[*it]]=niv[node];
}
}
void build(int node,int left,int right, int dec, int chain)
{
if(left==right)
{
arb[node+dec]=v[P[chain][left-1]];
return;
}
int mid=(left+right)/2;
build(node*2,left,mid,dec,chain);
build(node*2+1,mid+1,right,dec,chain);
arb[node+dec]=max(arb[node*2+dec],arb[node*2+1+dec]);
}
void make_paths()
{
niv[1]=1;
df(1);
for(int i=1;i<=nl;i++)
{
reverse(P[i].begin(),P[i].end());
if(i>1)
lPoz[i]= lPoz[i-1]+lD[i-1]*4;
build(1,1,lD[i],lPoz[i],i);
}
}
void update(int node,int left,int right,int pos,int val,int dec)
{
if(left==right)
{
arb[node+dec]=val;
return;
}
int mid=(left+right)/2;
if(pos<=mid)
update(node*2,left,mid,pos,val,dec);
else
update(node*2+1,mid+1,right,pos,val,dec);
arb[node+dec]=max(arb[node*2+dec],arb[node*2+1+dec]);
}
int query(int node,int left,int right,int ql,int qr,int dec)
{
if(ql<=left && right<=qr)
return arb[node+dec];
int mid=(left+right)/2,res=0;
if(ql<=mid)
res=max(res,query(node*2,left,mid,ql,qr,dec));
if(mid<qr)
res=max(res,query(node*2+1,mid+1,right,ql,qr,dec));
return res;
}
void solve()
{
int t,x,y,sol=0;
for(int i=1;i<=m;i++)
{
t = Op[i].first; x = Op[i].second.first, y = Op[i].second.second;
if(t==0)
update(1,1,lD[l[x]],niv[x]-lNiv[l[x]],y,lPoz[l[x]]);
else
{
sol=0;
while(1)
{
if(l[x]==l[y])
{
if(niv[x]==niv[y])
swap(x,y);
sol=max(sol,query(1,1,lD[l[x]],niv[x]-lNiv[l[x]],niv[y]-lNiv[l[y]],lPoz[l[x]]));
break;
}
if(lNiv[l[x]] < lNiv[l[y]] )
swap(x,y);
sol=max(sol,query(1,1,lD[l[x]],1,niv[x]-lNiv[l[x]],lPoz[l[x]]));
x=lDad[l[x]];
}
printf("%d\n",sol);
}
}
}
int main()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
read();
make_paths();
solve();
return 0;
}