#include <fstream>
#include <vector>
#define nmax 100005
using namespace std;
fstream f1("heavypath.in", ios::in);
fstream f2("heavypath.out", ios::out);
int n, m, val[nmax], t[nmax], siz[nmax], niv[nmax], urm[nmax], th[nmax], viz[nmax], nrl, sizlant[nmax], indl[nmax], poz[nmax];
vector<int> lant[nmax], v[nmax], aint[nmax];
void citire()
{
int i, x, y;
f1>>n>>m;
for(i=1; i<=n; i++)
f1>>val[i];
for(i=1; i<n; i++)
{
f1>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
}
void dfs(int nod)
{
viz[nod]=1;
siz[nod]=1;
for(auto it=v[nod].begin(); it!=v[nod].end(); ++it)
if(!viz[*it])
{
niv[*it]=niv[nod]+1;
dfs(*it);
siz[nod]+=siz[*it];
t[*it]=nod;
}
}
void dfs2(int nod)
{
if(siz[nod]==1)
{
nrl++;
lant[nrl].push_back(nod);
sizlant[nrl]=1;
indl[nod]=nrl;
poz[nod]=1;
}
else
{
int maxi=0, vec;
for(auto it=v[nod].begin(); it!=v[nod].end(); ++it)
if((*it!= t[nod])&&(maxi< siz[*it])) {maxi=siz[*it]; vec=*it;}
th[vec]=th[nod];
urm[nod]=vec;
dfs2(vec);
for(auto it=v[nod].begin(); it!=v[nod].end(); ++it)
if((*it!=t[nod])&&(*it!=vec))
{
th[*it]=*it;
dfs2(*it);
}
lant[indl[vec]].push_back(nod);
sizlant[indl[vec]]++;
indl[nod]=indl[vec];
poz[nod]=lant[indl[vec]].size();
}
}
///indl[nod]= indice lantului din care face parte nodul;
///poz[nod]=pozitie nod in lant
void update(int ind, int in, int st, int dr, int val, int poz)
{
if(st==dr) aint[ind][in]=val; //in=poz
else
{
int mijl=(st+dr)/2;
if(poz<=mijl) update(ind, in*2, st, mijl, val, poz);
else update(ind, in*2+1, mijl+1, dr, val, poz);
aint[ind][in]=max(aint[ind][in*2], aint[ind][in*2+1]);
}
}
void creeaza(int ind, int dim, vector<int> a)
{
int poz=1;
for(auto it=a.begin(); it!=a.end(); ++it, poz++)
update(ind, 1, 1, dim, val[*it], poz);
}
void drumuri()
{
for(int i=1; i<=nrl; i++)
{
aint[i].resize(sizlant[i]+5);
creeaza(i, sizlant[i], lant[i]);
}
}
int query(int ind, int in, int st, int dr, int l, int r)
{
if((l<=st)&&(dr<=r)) return aint[ind][in];
else
{
int mijl=(st+dr)/2, max1=0, max2=0;
if(l<=mijl) max1=query(ind, in*2, st, mijl, l, r);
if(mijl+1<=r) max2=query(ind, in*2+1, mijl+1, dr, l, r);
return max(max1, max2);
}
}
int query_heavy(int x, int y)
{
if(indl[x]==indl[y]) return query(indl[x], 1, 1, sizlant[indl[x]], min(poz[x], poz[y]), max(poz[x], poz[y]));
if(niv[th[x]]< niv[th[y]]) swap(x, y);
///urc x
int rez=query(indl[x], 1, 1, sizlant[indl[x]], min(poz[x], poz[th[x]]), max(poz[x], poz[th[x]]));
return max(rez,query_heavy(t[th[x]],y));
}
void queryuri()
{
int i, tip, x, y;
for(i=1; i<=m; i++)
{
f1>>tip>>x>>y;
if(tip==0) update(indl[x], 1, 1, sizlant[indl[x]], y, poz[x]);
else f2<<query_heavy(x, y)<<"\n";
}
}
int main()
{
citire();
dfs(1); th[1]=1;
dfs2(1);
drumuri();
queryuri();
return 0;
}