#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int nmax=100005;
vector<int> ve[nmax],drum[nmax];
bool be[nmax],viz[nmax];
int ndr,co[nmax],lv[nmax],ap[nmax];
int we[nmax],v[nmax],po[nmax],ta[nmax];
struct nod
{
int ma,st,dr;
nod * fiust,*fiudr;
nod()
{
fiust=fiudr=NULL;
ma=0;
}
};
nod * ai[nmax];
void init(int x)
{
we[x]=1;
for(int i=ve[x].size()-1; i>=0; i--)
if(lv[ve[x][i]]==0)
{
ta[ve[x][i]]=x;
lv[ve[x][i]]=lv[x]+1;
init(ve[x][i]);
we[x]+=we[ve[x][i]];
}
}
void baga(int x)
{
ndr++;
int i,j,l=0;
viz[x]=1;
while(x!=0)
{
drum[ndr].push_back(x);
po[x]=l;
ap[x]=ndr;
l++;
j=0;
for(i=ve[x].size()-1; i>=0; i--)
if(viz[ve[x][i]]==0)
{
if(j==0 || we[ve[x][i]]>we[j])
j=ve[x][i];
}
x=j;
viz[x]=1;
}
}
void prep(nod * root)
{
if(root->st!=root->dr)
{
int mi=(root->st+root->dr)/2;
root->fiust=new nod();
root->fiust->st=root->st;
root->fiust->dr=mi;
prep(root->fiust);
root->fiudr=new nod();
root->fiudr->st=mi+1;
root->fiudr->dr=root->dr;
prep(root->fiudr);
}
}
void update(nod * root,int x,int val)
{
if(x==root->st && x==root->dr)
{
root->ma=val;
}
else
{
int mi=(root->st+root->dr)/2;
if(x<=mi)
update(root->fiust,x,val);
else if(x>mi)
update(root->fiudr,x,val);
root->ma=max(root->fiust->ma,root->fiudr->ma);
}
}
int query(nod * root,int x,int y)
{
int ma=0;
int mi=(root->st+root->dr)/2;
if(x==root->st && y==root->dr)
{
ma=root->ma;
}
else
{
if(y<=mi)
ma=query(root->fiust,x,y);
else if(x>mi)
ma=query(root->fiudr,x,y);
else
{
ma=max(ma,query(root->fiust,x,mi));
ma=max(ma,query(root->fiudr,mi+1,y));
}
}
return ma;
}
int main()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
int n,t,i,j,x,y,q,st,dr,ti,ma;
scanf("%d%d",&n,&t);
for(i=1; i<=n; i++)
scanf("%d",&v[i]);
for(i=1; i<n; i++)
{
scanf("%d%d",&x,&y);
ve[x].push_back(y);
ve[y].push_back(x);
}
lv[1]=1;
init(1);
st=dr=1;
co[1]=1;
be[1]=1;
ndr=0;
while(st<=dr)
{
x=co[st];
for(i=ve[x].size()-1; i>=0; i--)
if(lv[ve[x][i]]==lv[x]+1)
{
dr++;
co[dr]=ve[x][i];
}
if(viz[x]==0)
baga(x);
st++;
}
for(i=1; i<=ndr; i++)
{
ai[i]=new nod();
ai[i]->st=0;
ai[i]->dr=drum[i].size()-1;
prep(ai[i]);
}
for(i=1;i<=n;i++)
{
update(ai[ap[i]],po[i],v[i]);
}
for(q=1; q<=t; q++)
{
scanf("%d%d%d",&ti,&x,&y);
if(ti==1)
{
ma=0;
while(ap[x]!=ap[y] && (x!=0 || y!=0))
{
if(lv[drum[ap[x]][0]]<lv[drum[ap[y]][0]])
swap(x,y);
ma=max(ma,query(ai[ap[x]],0,po[x]));
x=ta[drum[ap[x]][0]];
}
if(x!=0 && y!=0)
{
if(lv[x]<lv[y])
swap(x,y);
ma=max(ma,query(ai[ap[x]],po[y],po[x]));
}
printf("%d\n",ma);
}
else
update(ai[ap[x]],po[x],y);
}
return 0;
}