#include <fstream>
#include <vector>
#include <string.h>
#define nmax 100000
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
vector<int> arb[nmax+5];
vector<int> v[nmax+5];
vector<int> lanturi[nmax+5];
int val,pos,lef,righ;
int a[nmax+5],lvl[nmax+5],siz[nmax+5],nextintree[nmax+5];
int tatah[nmax+5],lant[nmax+5],nrlant,pozinlant[nmax+5],tata[nmax+5];
bool viz[nmax+5];
void update(int ind,int nod,int st,int dr)
{
if(st==dr)
{
arb[ind][nod]=val;
return ;
}
int mij=(st+dr)/2;
if(pos<=mij)
{
update(ind,nod*2,st,mij);
}
else
{
update(ind,nod*2+1,mij+1,dr);
}
arb[ind][nod]=max(arb[ind][nod*2],arb[ind][nod*2+1]);
}
int querry(int ind,int nod, int st,int dr)
{
if(lef<=st && dr<=righ)
{
return arb[ind][nod];
}
int mij=(st+dr)/2,ar=-1,al=-1;
if(lef<=mij)
{
al=querry(ind,nod*2,st,mij);
}
if(mij<righ)
{
ar=querry(ind,nod*2+1,mij+1,dr);
}
return max(ar,al);
}
int solve(int x,int y)
{
if(lant[x]==lant[y])
{
lef=pozinlant[x];
righ=pozinlant[y];
if(righ<lef)
swap(righ,lef);
return querry(lant[x],1,0,lanturi[lant[x]].size());
}
if(lvl[tatah[x]]<lvl[tatah[y]])
swap(x,y);
lef=0;
righ=pozinlant[x];
int ans=querry(lant[x],1,0,lanturi[lant[x]].size());
return max(ans,solve(tata[tatah[x]],y));
}
void constr(vector <int> v,int ind)
{
int i;
for(i=0;i<4*v.size()+5;i++)
arb[ind].push_back(0);
for(i=0;i<v.size();i++)
{
val=a[v[i]];
pos=i;
update(ind,1,0,v.size());
}
}
void calcsiz(int nod)//cal csiz[nod]+lvl[nod]+tata[vec]
{
int i,vec;
for(i=0;i<v[nod].size();i++)
{
vec=v[nod][i];
if(viz[vec]==0)
{
viz[vec]=1;
lvl[vec]=lvl[nod]+1;
tata[vec]=nod;
calcsiz(vec);
siz[nod]+=siz[vec];
}
}
siz[nod]++;
}
void DFS(int nod)
{
// tataH + next_in_tree+lant+pozinlant
int maxsiz=0,heavy=0,i,vec;
for(i=0;i<v[nod].size();i++)
{
vec=v[nod][i];
if(viz[vec]==0)
{
if(siz[vec]>maxsiz)
{
maxsiz=siz[vec];
heavy=vec;
}
}
}
nextintree[nod]=heavy;
for(i=0;i<v[nod].size();i++)
{
vec=v[nod][i];
if(viz[vec]==0)
{
if(vec==heavy)
{
tatah[vec]=tatah[nod];
lant[vec]=lant[nod];
}
else
{
tatah[vec]=vec;
nrlant++;
lant[vec]=nrlant;
}
pozinlant[vec]=lanturi[lant[vec]].size();
lanturi[lant[vec]].push_back(vec);
viz[vec]=1;
DFS(vec);
}
}
//????
}
int main()
{
int x,y,t,ind,n,m,i;
f>>n>>m;
for(i=1;i<=n;i++)
f>>a[i];
for(i=1;i<n;i++)
{
f>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
viz[1]=1;
calcsiz(1);
memset(viz,0,sizeof(viz));
//pentru 1
tatah[1]=1;
lant[1]=1;
pozinlant[1]=0;
lanturi[1].push_back(1);
nrlant=1;
viz[1]=1;
DFS(1);
//contstruiesc arbori pentru fiecare drum
for(i=1;i<=nrlant;i++)
{
constr(lanturi[i],i);
}
for(i=1;i<=m;i++)
{
f>>t>>x>>y;
if(t==0)
{
//update=> a[x]=y;
ind=lant[x];
val=y;
pos=pozinlant[x];
update(ind,1,0,lanturi[ind].size());
}
else
{
//querry()
g<<solve(x,y)<<'\n';
}
}
return 0;
}