#include <bits/stdc++.h>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int viz[100005],nr,nrpath,val[100005],primloc[100005],acum[200005],niv[200005],nrsub[100005],tatic[100005],rmq[20][200005],arb[400005],inceput[100005];
pair <int,int> pozitie[100005];
vector <int> v[100005];
vector <int> paths[200005];
void dfsrad (int x,int tata,int nivel)
{
int j,ok=0;
viz[x]=1;
nr++;
if (primloc[x]==0)
{
primloc[x]=nr;
}
acum[nr]=x;
niv[nr]=nivel;
for (j=0;j<v[x].size();j++)
{
int nod=v[x][j];
if (viz[nod]==0)
{
ok=1;
tatic[nod]=x;
dfsrad(nod,x,nivel+1);
nrsub[x]+=nrsub[nod];
nr++;
acum[nr]=x;
niv[nr]=nivel;
}
}
if (ok==0)
{
nrsub[x]=1;
}
}
int lca (int x,int y)
{
x=primloc[x];
y=primloc[y];
if (x>y)
{
swap(x,y);
}
if (x==y)
{
return acum[x];
}
int lg=log2(y-x);
if (niv[rmq[lg][x]]>niv[rmq[lg][y-(1<<lg)+1]])
{
return acum[rmq[lg][y-(1<<lg)+1]];
}
return acum[rmq[lg][x]];
}
void dfsheavy(int x)
{
int j,maxim=0,loc=0;
viz[x]=1;
for (j=0;j<v[x].size();j++)
{
int nod=v[x][j];
if (viz[nod]==0&&nrsub[nod]>maxim)
{
maxim=nrsub[nod];
loc=nod;
}
}
if (loc!=0)
{
paths[nrpath].push_back(loc);
inceput[loc]=paths[nrpath][0];
pozitie[loc]={nrpath,paths[nrpath].size()-1};
dfsheavy(loc);
}
}
void update (int st,int dr,int nod,int poz,int val)
{
if (st==dr)
{
arb[nod]=val;
return;
}
int mij=(st+dr)/2;
if (poz<=mij)
{
update(st,mij,2*nod,poz,val);
}
else
{
update(mij+1,dr,2*nod+1,poz,val);
}
arb[nod]=max(arb[2*nod],arb[2*nod+1]);
}
int queryarb (int st,int dr,int nod ,int ua,int ub)
{
if (ua<=st&&dr<=ub)
{
return arb[nod];
}
int mij=(st+dr)/2;
int r1=INT_MIN,r2=INT_MIN;
if (ua<=mij)
{
r1=queryarb(st,mij,2*nod,ua,ub);
}
if (mij<ub)
{
r2=queryarb(mij+1,dr,2*nod+1,ua,ub);
}
return max(r1,r2);
}
int n,m,i,x,y,lg,putere,j,tip;
int query (int st,int dr)
{
int copie,solutie,indice,pozitieelem;
solutie=0;
copie=st;
while (copie!=dr)
{
pozitieelem=pozitie[copie].second;
indice=pozitie[copie].first;
if (pozitie[dr].first==pozitie[copie].first)
{
solutie=max(solutie,queryarb(1,n,1,pozitie[dr].second,pozitie[copie].second));
copie=dr;
}
else
{
solutie=max(solutie,queryarb(1,n,1,pozitie[paths[indice][0]].second,pozitie[copie].second));
copie=paths[pozitie[copie].first][0];
if (copie!=dr)
{
copie=tatic[copie];
}
}
}
solutie=max(solutie,val[dr]);
return solutie;
}
int pozitie2;
int main()
{
f>>n>>m;
for (i=1;i<=n;i++)
{
f>>val[i];
}
for (i=1;i<=n-1;i++)
{
f>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfsrad(1,0,1);
for (i=1;i<=nr;i++)
{
rmq[0][i]=i;
}
lg=log2(nr);
for (i=1;i<=lg;i++)
{
putere=(1<<(i-1));
for (j=1;j<=nr-putere+1;j++)
{
if (niv[rmq[i-1][j]]>niv[rmq[i-1][j+putere]])
{
rmq[i][j]=rmq[i-1][j+putere];
}
else
{
rmq[i][j]=rmq[i-1][j];
}
}
}
memset(viz,0,sizeof(viz));
for (i=1;i<=n;i++)
{
if (viz[i]==0)
{
nrpath++;
paths[nrpath].push_back(i);
pozitie[i]={nrpath,0};
dfsheavy(i);
}
}
pozitie2=0;
for (i=1;i<=nrpath;i++)
{
for (j=0;j<paths[i].size();j++)
{
pozitie2++;
update(1,n,1,pozitie2,val[paths[i][j]]);
pozitie[paths[i][j]].second=pozitie2;
}
}
for (m;m--;)
{
f>>tip>>x>>y;
if (tip==1)
{
int lowestca=lca(x,y);
g<<max(query(x,lowestca),query(y,lowestca))<<'\n';
}
else
{
/// indice =pozitie[x].first;
/// pozitie =pozitie[x].second;
update(1,n,1,pozitie[x].second,y);
val[x]=y;
}
}
return 0;
}