#include <cstdio>
#include <vector>
#define dimbuff 1000000
using namespace std;
FILE *fin=fopen ("heavypath.in","r");
FILE *fout=fopen ("heavypath.out","w");
int n,q,i,x,y,sol,ch,nrr;
int niv,st,dr,nr,nod,val;
int tata[100001],poz[100001],nivel[100001];
int lg[100001],dp[100001],nivinit[100001],t[100001],lant[100001],valnr[100001];
vector <int> v[100001],noduri[100001];
char buff[dimbuff+5];
int pp;
int numar()
{
int val=0;
while (!(buff[pp]>='0'&&buff[pp]<='9'))
{
pp++;
if (pp==dimbuff)
{
fread(buff,1,dimbuff,fin);
pp=0;
}
}
while (buff[pp]>='0'&&buff[pp]<='9')
{
val=val*10+buff[pp]-'0';
pp++;
if (pp==dimbuff)
{
fread (buff,1,dimbuff,fin);
pp=0;
}
}
return val;
}
class segtree
{
private:
vector <int> v;
public:
void marime (int n)
{
v.resize (4*n+1,0);
}
void build (int nod,int st,int dr)
{
if (st==dr)
v[nod]=valnr[st];
else
{
int mij=(st+dr)/2;
build (2*nod,st,mij);
build (2*nod+1,mij+1,dr);
v[nod]=max (v[2*nod],v[2*nod+1]);
}
}
void update (int nod,int st,int dr,int poz,int val)
{
if (st==dr)
v[nod]=val;
else
{
int mij=(st+dr)/2;
if (poz<=mij)
update (2*nod,st,mij,poz,val);
else
update (2*nod+1,mij+1,dr,poz,val);
v[nod]=max (v[2*nod],v[2*nod+1]);
}
}
void query (int nod,int st,int dr,int a,int b,int &sol)
{
if (st>=a&&dr<=b)
sol=max (sol,v[nod]);
else
{
int mij=(st+dr)/2;
if (a<=mij)
query (2*nod,st,mij,a,b,sol);
if (b>=mij+1)
query (2*nod+1,mij+1,dr,a,b,sol);
}
}
};
segtree aint[100001];
void dfs (int nod,int t,int niv)
{
nivinit[nod]=niv;
for (int i=0; i<v[nod].size (); i++)
{
int vecin=v[nod][i];
if (vecin!=t)
{
dfs (vecin,nod,niv+1);
if (dp[vecin]>dp[nod])
{
dp[nod]=dp[vecin];
poz[nod]=vecin;
}
}
}
dp[nod]++;
}
void dfs_lant (int nod,int tt)
{
nrr++;
int nr=nrr;
t[nr]=nod;
int niv=0;
while (nod!=0)
{
noduri[nr].push_back (nod);
for (int i=0; i<v[nod].size (); i++)
{
int vecin=v[nod][i];
if (vecin!=tt&&vecin!=poz[nod])
dfs_lant (vecin,nod);
}
niv++;
lant[nod]=nr;
nivel[nod]=niv;
tata[nod]=tt;
tt=nod;
nod=poz[nod];
}
aint[nr].marime (niv);
lg[nr]=niv;
for (int i=0; i<noduri[nr].size (); i++)
aint[nr].update (1,1,niv,i+1,valnr[noduri[nr][i]]);
}
int main ()
{
n=numar ();
q=numar ();
for (i=1; i<=n; i++)
valnr[i]=numar ();
for (i=1; i<n; i++)
{
x=numar ();
y=numar ();
v[x].push_back (y);
v[y].push_back (x);
}
dfs (1,0,1);
dfs_lant (1,0);
while (q--)
{
ch=numar ();
if (ch==0)
{
nod=numar ();
val=numar ();
aint[lant[nod]].update (1,1,lg[lant[nod]],nivel[nod],val);
}
else
{
x=numar ();
y=numar ();
sol=0;
while (lant[x]!=lant[y])
{
if (nivinit[t[lant[x]]]>=nivinit[t[lant[y]]])
{
aint[lant[x]].query (1,1,lg[lant[x]],1,nivel[x],sol);
x=tata[t[lant[x]]];
}
else
{
aint[lant[y]].query (1,1,lg[lant[y]],1,nivel[y],sol);
y=tata[t[lant[y]]];
}
}
st=min (nivel[x],nivel[y]);
dr=max (nivel[x],nivel[y]);
aint[lant[x]].query (1,1,lg[lant[x]],st,dr,sol);
fprintf (fout,"%d\n",sol);
}
}
return 0;
}