#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int NMAX = 100005;
int i,N,M,X,Y,Paths,T,poz,val,A,B,Sol;
int Val[NMAX],SubArb[NMAX],Lant[NMAX],Father[NMAX],Lev[NMAX],Poz[NMAX];
vector<int> V[NMAX],P[NMAX],Arb[NMAX];
void Read()
{
freopen("heavypath.in","r",stdin);
freopen("heavypath.out","w",stdout);
scanf("%d%d",&N,&M);
for(i=1;i<=N;i++) scanf("%d",&Val[i]);
for(i=1;i<N;i++)
{
scanf("%d%d",&X,&Y);
V[X].push_back(Y);
V[Y].push_back(X);
}
}
void DFS(int Node,int Niv,int Dad)
{
SubArb[Node]=1; Lev[Node]=Niv;
for(vector<int>::iterator it=V[Node].begin();it!=V[Node].end();it++)
if(*it!=Dad)
{
Father[*it]=Node;
DFS(*it,Niv+1,Node);
SubArb[Node]+=SubArb[*it];
}
if(V[Node].size()==1 && Node!=1)
{
Lant[Node]=++Paths; P[Paths].push_back(0);
P[Paths].push_back(Node); Poz[Node]=1; return;
}
int MaxSon=0;
for(vector<int>::iterator it=V[Node].begin();it!=V[Node].end();it++)
if(*it!=Dad && SubArb[*it]>SubArb[MaxSon]) MaxSon=*it;
Lant[Node]=Lant[MaxSon];
P[Lant[Node]].push_back(Node);
Poz[Node]=P[Lant[Node]].size()-1;
}
void Build(int Node,int Left,int Right,int Path)
{
if(Left==Right) {Arb[Path][Node]=Val[P[Path][Left]]; return;}
int Middle=(Left+Right)/2;
int LS=2*Node; int RS=LS+1;
Build(LS,Left,Middle,Path);
Build(RS,Middle+1,Right,Path);
Arb[Path][Node]=max(Arb[Path][LS],Arb[Path][RS]);
}
void Update(int Node,int Left,int Right,int Path)
{
if(Left==Right) {Arb[Path][Node]=val; return;}
int Middle=(Left+Right)/2;
int LS=2*Node; int RS=LS+1;
if(poz<=Middle) Update(LS,Left,Middle,Path);
else Update(RS,Middle+1,Right,Path);
Arb[Path][Node]=max(Arb[Path][LS],Arb[Path][RS]);
}
void Query(int Node,int Left,int Right,int Path)
{
if(Left>=A && Right<=B) {Sol=max(Sol,Arb[Path][Node]); return;}
int Middle=(Left+Right)/2;
int LS=2*Node; int RS=LS+1;
if(A<=Middle) Query(LS,Left,Middle,Path);
if(B>Middle) Query(RS,Middle+1,Right,Path);
}
int FindMax(int X,int Y)
{
Sol=0;
for(;;)
{
if(Lant[X]==Lant[Y])
{
A=min(Poz[X],Poz[Y]);
B=max(Poz[X],Poz[Y]);
Query(1,1,P[Lant[X]].size()-1,Lant[X]);
break;
}
if(Lev[P[Lant[X]][1]]<Lev[P[Lant[Y]][1]]) swap(X,Y);
A=1; B=Poz[X]; Query(1,1,P[Lant[X]].size()-1,Lant[X]);
X=Father[P[Lant[X]][1]];
}
return Sol;
}
void Solve()
{
DFS(1,1,0);
for(i=1;i<=Paths;i++)
{
reverse(P[i].begin()+1,P[i].end());
Arb[i].resize(4*(P[i].size())+5);
Build(1,1,P[i].size()-1,i);
}
for(i=1;i<=N;i++) Poz[i]=P[Lant[i]].size()-Poz[i];
for(;M;M--)
{
scanf("%d%d%d",&T,&X,&Y);
if(T) printf("%d\n",FindMax(X,Y));
else
{
poz=Poz[X]; val=Y;
Update(1,1,P[Lant[X]].size()-1,Lant[X]);
}
}
}
int main()
{
Read();
Solve();
return 0;
}