#include <bits/stdc++.h>
#define Dim 100010
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int N,M,Val[Dim],a,b,DX[Dim],cnt=1,Label[Dim],Poz[Dim],Roof[Dim];
int Tree[4*Dim],Gap[Dim],numara,op,x,y,ans,LimA,LimB,Level[Dim];
bool viz[Dim];
vector <int> V[Dim],Chain[Dim];
void init()
{
for(int i=1;i<=N;i++) viz[i]=0;
}
void DFS(int nod,int lvl)
{
viz[nod]=1;
Level[nod]=lvl;
for(unsigned int i=0;i<V[nod].size();i++)
{
int vecin=V[nod][i];
if(!viz[vecin])
{
DFS(vecin,lvl+1);
DX[nod]+=DX[vecin];
}
}
}
void Build(int nod,int index)
{
viz[nod]=1;
Label[nod]=cnt;
Poz[nod]=index;
Chain[cnt].push_back(nod);
pair <int,int> pii;
for(unsigned int i=0;i<V[nod].size()&&DX[nod]!=1;i++)
{
int vecin=V[nod][i];
if(!viz[vecin]&&DX[vecin]>pii.second) pii={vecin,DX[vecin]};
if(i==V[nod].size()-1) Build(pii.first,index+1);
}
for(unsigned int i=0;i<V[nod].size();i++)
{
int vecin=V[nod][i];
if(!viz[vecin])
{
cnt++;
Roof[cnt]=nod;
Build(vecin,1);
}
}
}
void Make(int nod,int st,int dr,int lant,int defazaj)
{
if(st==dr)
{
numara++;
Tree[nod+defazaj]=Val[Chain[lant][numara]];
return;
}
int mij=(st+dr)/2;
Make(2*nod,st,mij,lant,defazaj);
Make(2*nod+1,mij+1,dr,lant,defazaj);
Tree[nod+defazaj]=max(Tree[2*nod+defazaj],Tree[2*nod+1+defazaj]);
}
void Update(int nod,int st,int dr,int defazaj)
{
if(st==dr)
{
Tree[nod+defazaj]=y;
return;
}
int mij=(st+dr)/2;
if(Poz[x]<=mij)
Update(2*nod,st,mij,defazaj);
if(Poz[x]>=mij+1)
Update(2*nod+1,mij+1,dr,defazaj);
Tree[nod+defazaj]=max(Tree[2*nod+defazaj],Tree[2*nod+1+defazaj]);
}
void Query(int nod,int st,int dr,int defazaj)
{
if(st>=LimA&&dr<=LimB)
{
ans=max(ans,Tree[nod+defazaj]);
return;
}
int mij=(st+dr)/2;
if(LimA<=mij)
Query(2*nod,st,mij,defazaj);
if(LimB>=mij+1)
Query(2*nod+1,mij+1,dr,defazaj);
}
int main()
{
f>>N>>M;
for(int i=1;i<=N;i++)
{
f>>Val[i];
DX[i]=1;
}
for(int i=1;i<N;i++)
{
f>>a>>b;
V[a].push_back(b);
V[b].push_back(a);
}
DFS(1,1); init();
Build(1,1); init();
for(int i=1;i<=cnt;i++)
{
numara=-1;
if(i>1) Gap[i]=Gap[i-1]+4*Chain[i-1].size();
Make(1,1,Chain[i].size(),i,Gap[i]);
}
for(int i=1;i<=M;i++)
{
f>>op>>x>>y;
if(!op)
{
Update(1,1,Chain[Label[x]].size(),Gap[Label[x]]);
}
else
{
ans=0;
while(Label[x]!=Label[y])
{
if(Level[Roof[Label[x]]]<Level[Roof[Label[y]]]) swap(x,y);
LimA=1; LimB=Poz[x];
Query(1,1,Chain[Label[x]].size(),Gap[Label[x]]);
x=Roof[Label[x]];
}
if(Label[x]==Label[y])
{
if(Poz[x]>Poz[y]) swap(x,y);
LimA=Poz[x]; LimB=Poz[y];
Query(1,1,Chain[Label[x]].size(),Gap[Label[x]]);
}
g<<ans<<'\n';
}
}
return 0;
}