#include <fstream>
#include <vector>
#include <algorithm>
#define pb push_back
#define mkp make_pair
#define piii pair<int, pair<int, int> >
#define nMax 100005
#define qMax 100005
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, m, Sol, nL;
int v[nMax], niv[nMax], lNiv[nMax], lTata[nMax], w[nMax], viz[nMax], l[nMax], arb[4*nMax], lDim[nMax], lPoz[nMax];
piii q[qMax];
vector<int> G[nMax], P[nMax];
void read()
{
int op, a, b;
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>v[i];
for(int i=1;i<n;i++)
{
fin>>a>>b;
G[a].pb(b);
G[b].pb(a);
}
for(int i=1;i<=m;i++)
{
fin>>op>>a>>b;
q[i]=mkp(op, mkp(a, b));
}
}
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[fiu]>w[hN])
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];
}
}
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 upDate(int node, int st, int dr, int decalaj, int poz, int val)
{
if(st==dr)
{
arb[node+decalaj]=val;
return;
}
int mid=st+(dr-st)/2;
if(poz<=mid)
upDate(2*node, st, mid, decalaj, poz, val);
else
upDate(2*node+1, mid+1, dr, decalaj, poz, val);
arb[node+decalaj]=max(arb[2*node+decalaj], arb[2*node+1+decalaj]);
}
int query(int node, int st, int dr, int decalaj, int pozst, int pozdr)
{
int Max=0;
if(pozst<=st && pozdr>=dr)
return arb[node+decalaj];
int mid=st+(dr-st)/2;
if(pozst<=mid)
Max=max(Max, query(2*node, st, mid, decalaj, pozst, pozdr));
if(pozdr>mid)
Max=max(Max, query(2*node+1, mid+1, dr, decalaj, pozst, pozdr));
return Max;
}
void write()
{
fout<<Sol<<'\n';
}
void solve()
{
int op, a, b;
for(int i=1;i<=m;i++)
{
op=q[i].first, a=q[i].second.first, b=q[i].second.second;
if(op==0)
{
upDate(1, 1, lDim[l[a]], lPoz[l[a]], niv[a]-lNiv[l[a]], b);
continue;
}
if(op==1)
{
Sol=0;
while(1)
{
if(l[a]==l[b])
{
if(niv[a]>niv[b])
swap(a, b);
Sol=max(Sol, query(1, 1, lDim[l[a]], lPoz[l[a]], niv[a]-lNiv[l[a]], niv[b]-lNiv[l[a]]));
write();
break;
}
else
{
if(lNiv[l[a]]>lNiv[l[b]])
swap(a, b);
Sol=max(Sol, query(1, 1, lDim[l[b]], lPoz[l[b]], 1, niv[b]-lNiv[l[b]]));
b=lTata[l[b]];
}
}
}
}
}
int main()
{
read();
make_paths();
solve();
return 0;
}