#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int NMAX=100005;
int n,m,len,a[NMAX],sub[NMAX],fat[NMAX],niv[NMAX];
int poz[NMAX],path[NMAX];
vector<int>v[NMAX];
vector<int>aint[NMAX],see[NMAX];
void Dfs(int x,int f)
{
sub[x]=1;niv[x]=niv[f]+1;
int node=0;
for (auto it : v[x])
if (it!=f)
{
Dfs(it,x);
sub[x]+=sub[it];
if (sub[it]>sub[node]) node=it;
}
if (!node)
{
len++;
poz[x]=1;path[x]=len;
see[len].push_back(x);
}
else
{
poz[x]=poz[node]+1;
path[x]=path[node];
see[path[x]].push_back(x);
}
for (auto it : v[x])
if (it!=node && it!=f)
fat[path[it]]=x;
}
void Update(int nod,int st,int dr,int poz,int val,int in)
{
if (st==dr) aint[in][nod]=val;
else
{
int mij=(st+dr)>>1;
if (poz<=mij) Update(2*nod,st,mij,poz,val,in);
if (poz>mij) Update(2*nod+1,mij+1,dr,poz,val,in);
aint[in][nod]=max(aint[in][2*nod],aint[in][2*nod+1]);
}
}
int Query(int nod,int st,int dr,int c,int d,int in)
{
if (c<=st && dr<=d) return aint[in][nod];
else
{
int mij=(st+dr)>>1,rez=0;
if (c<=mij) rez=max(rez,Query(2*nod,st,mij,c,d,in));
if (d>mij) rez=max(rez,Query(2*nod+1,mij+1,dr,c,d,in));
return rez;
}
}
int main()
{
int i,x,y,op,sol;
fin>>n>>m;
for (i=1;i<=n;i++) fin>>a[i];
for (i=1;i<n;i++)
{
fin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
Dfs(1,0);
for (i=1;i<=len;i++)
{
aint[i].resize(see[i].size()*4 + 5,0);
for (auto it : see[i])
Update(1,1,see[i].size(),poz[it],a[it],i);
}
for (i=1;i<=m;i++)
{
fin>>op>>x>>y;
if (op==0) Update(1,1,see[path[x]].size(),poz[x],y,path[x]);
if (op==1)
{
sol=0;
while (path[x]!=path[y])
{
if (niv[fat[path[x]]]>=niv[fat[path[y]]])//urc cu x
{
sol=max(sol,Query(1,1,see[path[x]].size(),poz[x],see[path[x]].size(),path[x]));
x=fat[path[x]];
}
else//urc cu y
{
sol=max(sol,Query(1,1,see[path[y]].size(),poz[y],see[path[y]].size(),path[y]));
y=fat[path[y]];
}
}
//ambii sunt pe acelasi lant,al lca-ului
if (poz[x]>poz[y]) swap(x,y);
sol=max(sol,Query(1,1,see[path[x]].size(),poz[x],poz[y],path[x]));
fout<<sol<<"\n";
}
}
return 0;
}