#include <bits/stdc++.h>
#define Dim 100009
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
void query();
int N,M,x,a,b,dx[Dim],val[Dim],cnt=1,T;
int label[Dim],poz[Dim],roof[Dim],Deep[2*Dim+10],Euler[2*Dim+10],First[Dim];
int rmq[18][2*Dim+10],Level[Dim],lca,cont_chain;
int ID_chain[Dim],Tree[4*Dim+10],numara,MAX;
int LIMA,LIMB,supremlider,vertex;
bool viz[Dim],viz2[Dim],viz3[Dim];
vector <int> V[Dim];
vector < pair<int,int> > Lant[Dim];
void DFS_nod(int nod)
{
viz[nod]=1;
for(unsigned int i=0;i<V[nod].size();i++)
{
int vecin=V[nod][i];
if(!viz[vecin])
{
DFS_nod(vecin);
dx[nod]+=dx[vecin];
}
}
}
void Build_chain(int nod,int index)
{
viz2[nod]=1;
poz[nod]=index;
label[nod]=cnt;
Lant[cnt].push_back({nod,index});
pair <int,int> which;
for(unsigned int i=0;i<V[nod].size();i++)
{
int vecin=V[nod][i];
if(!viz2[vecin])
if(dx[vecin]>which.first) which={dx[vecin],vecin};
if(i==V[nod].size()-1)
{
Build_chain(which.second,index+1);
}
}
for(unsigned int i=0;i<V[nod].size();i++)
{
int vecin=V[nod][i];
if(!viz2[vecin]&&vecin!=which.second)
{
cnt++;
roof[cnt]=nod;
Build_chain(vecin,1);
}
}
}
void DFS(int nod,int level)
{
viz3[nod]=1;
Level[nod]=level;
Euler[++cnt]=nod;
Deep[cnt]=level;
First[nod]=cnt;
for(unsigned int i=0;i<V[nod].size();i++)
{
int vecin=V[nod][i];
if(!viz3[vecin])
{
DFS(vecin,level+1);
Euler[++cnt]=nod;
Deep[cnt]=level;
}
}
}
void RMQ()
{
for(int i=1;i<=cnt;i++) rmq[0][i]=i;
for(int i=1;(1<<i)<=cnt;i++)
for(int j=1;j+(1<<i)-1<=cnt;j++)
{
a=rmq[i-1][j];
b=rmq[i-1][j+(1<<(i-1))];
if(Deep[a]<=Deep[b]) rmq[i][j]=a;
else rmq[i][j]=b;
}
}
int LCA(int X,int Y)
{
int prim1=First[X];
int prim2=First[Y];
if(prim1>prim2) swap(prim1,prim2);
int dif=log2(prim2-prim1+1);
int care1=rmq[dif][prim1];
int care2=rmq[dif][prim2-(1<<dif)+1];
if(Deep[care1]<=Deep[care2])
return Euler[care1];
else
return Euler[care2];
}
void Build(int nod,int st,int dr)
{
if(st==dr)
{
Tree[nod+ID_chain[T]]=val[Lant[T][++numara].first];
return;
}
int mij=(st+dr)/2;
Build(2*nod,st,mij);
Build(2*nod+1,mij+1,dr);
Tree[nod+ID_chain[T]]=max(Tree[2*nod+ID_chain[T]],Tree[2*nod+1+ID_chain[T]]);
}
void query(int nod,int st,int dr,int defazaj)
{
if(st>=LIMA&&dr<=LIMB)
{
supremlider=max(Tree[nod+defazaj],supremlider);
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);
}
void Solve(int X,int Y)
{
bool ok=1;
while(ok)
{
if(label[X]==label[Y])
{
LIMA=poz[X]; LIMB=poz[Y];
supremlider=0;
query(1,1,Lant[label[X]].size(),ID_chain[label[X]]);
//if(T==6) cout<<X<<" "<<Y<<" "<<LIMA<<" "<<LIMB<<" "<<label[X]<<" "<<ID_chain[label[X]]<<'\n';
MAX=max(MAX,supremlider);
ok=0;
return;
}
else
{
LIMA=1; LIMB=poz[Y];
supremlider=0;
query(1,1,Lant[label[Y]].size(),ID_chain[label[Y]]);
MAX=max(MAX,supremlider);
Y=roof[label[Y]];
}
}
}
void Update(int nod,int st,int dr,int defazaj)
{
if(st==dr&&st==a)
{
Tree[nod+defazaj]=b;
return;
}
int mij=(st+dr)/2;
if(a<=mij)
Update(2*nod,st,mij,defazaj);
else
Update(2*nod+1,mij+1,dr,defazaj);
Tree[nod+defazaj]=max(Tree[2*nod+defazaj],Tree[2*nod+1+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_nod(1);
roof[1]=1;
Build_chain(1,1);
cont_chain=cnt; cnt=0;
DFS(1,1);
RMQ();
for(int i=1;i<=cont_chain;i++) Lant[i].erase(Lant[i].begin()+Lant[i].size());
/*for(T=1;T<=cont_chain;T++)
{
cout<<roof[T]<<'\n';
for(int i=0;i<Lant[T].size();i++) cout<<Lant[T][i].first<<" "<<Lant[T][i].second<<'\n';
cout<<'\n'<<'\n';
} cout<<label[2]<<" "<<label[9]<<'\n';
*/
for(T=1;T<=cont_chain;T++)
{
numara=-1;
if(T>1) ID_chain[T]=ID_chain[T-1]+4*Lant[T].size();
Build(1,1,Lant[T].size());
}
for(T=1;T<=M;T++)
{
f>>x>>a>>b;
lca=LCA(a,b);
if(x)
{
MAX=0;
Solve(lca,a);
Solve(lca,b);
g<<MAX<<'\n';
}
else
{
Update(1,1,Lant[label[a]].size(),ID_chain[label[a]]);
}
}
return 0;
}