#include<fstream>
#include<vector>
#include<algorithm>
#define pb push_back
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int DN=1e5+5;
int n,m,a[DN],f,g;
int type;
int cnt[DN],nr,fz[DN],pr2[DN],pr[DN];
int arb[4*DN],niv[DN],de[DN],ls,ld,ma;
int poz,val;
vector<int>v[DN];
void dfs(int nod)
{
int frunza=1,ma=0,z;
cnt[nod]=1;
for(auto i:v[nod])
if(i!=pr[nod])
{
pr[i]=nod;
niv[i]=niv[nod]+1;
dfs(i);
cnt[nod]+=cnt[i];
frunza=0;
if(cnt[i]>ma)
{
ma=cnt[i];
z=i;
}
}
if(frunza)
{
nr++;
fz[nod]=nr;
return;
}
for(auto i:v[nod])
if(i!=pr[nod]&&i!=z)
pr2[fz[i]]=nod;
fz[nod]=fz[z];
}
void update(int nod,int st,int dr,int decalaj)
{
if(st==dr)
{
arb[nod+decalaj]=val;
return;
}
int mij=(st+dr)/2;
if(poz<=mij)
update(2*nod,st,mij,decalaj);
else
update(2*nod+1,mij+1,dr,decalaj);
arb[nod+decalaj]=max(arb[2*nod+decalaj],arb[2*nod+1+decalaj]);
}
void modifica(int nod)
{
poz=niv[nod]-niv[pr2[fz[nod]]];
update(1,1,cnt[fz[nod]],de[fz[nod]]);
}
void query(int nod,int st,int dr,int decalaj)
{
if(ls<=st&&dr<=ld)
{
ma=max(ma,arb[nod+decalaj]);
return;
}
int mij=(st+dr)/2;
if(ls<=mij)
query(2*nod,st,mij,decalaj);
if(mij<ld)
query(2*nod+1,mij+1,dr,decalaj);
}
void solve(int f,int g)
{
while(niv[f]>=niv[g])
{
ls=max(1,niv[g]-niv[pr2[fz[f]]]);
ld=niv[f]-niv[pr2[fz[f]]];
query(1,1,cnt[fz[f]],de[fz[f]]);
f=pr2[fz[f]];
}
}
int lca(int f,int g)
{
while(pr2[f]!=pr2[g])
{
if(niv[f]>niv[g])
f=pr2[f];
else
g=pr2[g];
}
if(niv[f]<=niv[g])
return f;
return g;
}
int main()
{
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>a[i];
for(int i=1;i<n;i++)
{
fin>>f>>g;
v[f].pb(g);
v[g].pb(f);
}
niv[1]=1;
dfs(1);
for(int i=1;i<=n;i++)
cnt[i]=0;
for(int i=1;i<=n;i++)
cnt[fz[i]]++;
for(int i=1;i<=nr;i++)
de[i]=de[i-1]+4*cnt[i-1];
for(int i=1;i<=n;i++)
{
val=a[i];
modifica(i);
}
while(m--)
{
fin>>type;
if(type==0)
{
fin>>f>>val;
modifica(f);
continue;
}
fin>>f>>g;
ma=0;
int k=lca(f,g);
solve(f,k);
solve(g,k);
fout<<ma<<'\n';
}
}