//heavy path decomposition(numar de fii lant) - n * (log(n)^2)
#include <fstream>
#include <vector>
#include <algorithm>
#define nMax 100005
#define pb push_back
#define mkp make_pair
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int niv[nMax], lNiv[nMax], lTata[nMax], viz[nMax], w[nMax], l[nMax], n, m, nL, sol, v[nMax], lPoz[nMax], lDim[nMax], arb[4*nMax];
vector<int> G[nMax], P[nMax];
pair<int, pair<int, int> > op[nMax];
void read()
{
int t, x, y;
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>v[i];
for(int i=1;i<n;i++)
{
fin>>x>>y;
G[x].pb(y);
G[y].pb(x);
}
for(int i=1;i<=m;i++)
{
fin>>t>>x>>y;
op[i]=mkp(t, mkp(x, y));
}
}
void dfs(int node)
{
viz[node]=1;
w[node]=1;
int frunza=1, hN=-1;
for(vector<int>::iterator it=G[node].begin();it!=G[node].end();it++)
{
int fiu=*it;
if(viz[fiu])
continue;
frunza=0;
niv[fiu]=niv[node]+1;
dfs(fiu);
w[node]+=w[fiu];
if(hN==-1)
hN=fiu;
else
if(w[hN]<w[fiu])
hN=fiu;
}
if(frunza)
{
l[node]=++nL;
lDim[nL]++;
P[nL].pb(node);
return;
}
l[node]=l[hN];
++lDim[l[node]];
P[l[node]].pb(node);
for(vector<int>::iterator it=G[node].begin();it!=G[node].end();it++)
{
int fiu=*it;
if(fiu==hN || niv[fiu]<niv[node])
continue;
lTata[l[fiu]]=node;
lNiv[l[fiu]]=niv[node];
}
}
int query(int node, int st, int dr, int pozst, int pozdr, int decalaj)
{
int rez=0;
if(pozst<=st && pozdr>=dr)
return arb[node+decalaj];
int mid=st+(dr-st)/2;
if(pozst<=mid)
rez=max(rez, query(2*node, st, mid, pozst, pozdr, decalaj));
if(pozdr>mid)
rez=max(rez, query(2*node+1, mid+1, dr, pozst, pozdr, decalaj));
return rez;
}
void upDate(int node, int st, int dr, int poz, int val, int decalaj)
{
if(st==dr)
{
arb[node+decalaj]=val;
return;
}
int mid=st+(dr-st)/2;
if(poz<=mid)
upDate(2*node, st, mid, poz, val, decalaj);
else
upDate(2*node+1, mid+1, dr, poz, val, decalaj);
arb[node+decalaj]=max(arb[2*node+decalaj], arb[2*node+1+decalaj]);
}
void build(int node, int st, int dr, int decalaj, int lant)
{
if(st==dr)
{
arb[node+decalaj]=v[P[lant][st-1]];
return;
}
int mid=st+(dr-st)/2;
build(2*node, st, mid, decalaj, lant);
build(2*node+1, mid+1, dr, decalaj, lant);
arb[node+decalaj]=max(arb[2*node+decalaj], arb[2*node+1+decalaj]);
}
void make_paths()
{
niv[1]=1;
dfs(1);
for(int i=1;i<=nL;i++)
{
reverse(P[i].begin(), P[i].end());
if(i>1)
lPoz[i]=lPoz[i-1]+lDim[i-1]*4;
build(1, 1, lDim[i], lPoz[i], i);
}
}
void write()
{
fout<<sol<<'\n';
}
void solve()
{
int t, x, y;
for(int i=1;i<=m;i++)
{
t=op[i].first, x=op[i].second.first, y=op[i].second.second;
if(t==0)
upDate(1, 1, lDim[l[x]], niv[x]-lNiv[l[x]], y, lPoz[l[x]]);
else
{
sol=0;
while(1)
{
if(l[x]==l[y])
{
if(niv[x]>niv[y])
swap(x, y);
sol=max(sol, query(1, 1, lDim[l[x]], niv[x]-lNiv[l[x]], niv[y]-lNiv[l[x]], lPoz[l[x]]));
break;
}
if(lNiv[l[x]]>lNiv[l[y]])
swap(x, y);
sol=max(sol, query(1, 1, lDim[l[y]], 1, niv[y]-lNiv[l[y]], lPoz[l[y]]));
y=lTata[l[y]];
}
write();
}
}
}
int main()
{
read();
make_paths();
solve();
return 0;
}