#include <bits/stdc++.h>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int niv[100001],w[100001],v[100001],aint[400004],head[100001],nou[100001],poz[100001],tata[100001],k,n,m;
vector <int> a[100001];
void dfs(int x)
{ w[x]=1;
for (auto y:a[x])
if (y!=tata[x])
{
tata[y]=x;
niv[y]=niv[x]+1;
dfs(y);
w[x]+=w[y];
}
}
void dfs_heavy(int x)
{
int heavy=0;
nou[++k]=x;
poz[x]=k;
for (auto y:a[x])
if (y!=tata[x] && w[y]>w[heavy])
heavy=y;
if (heavy!=0)
{
head[heavy]=head[x];
dfs_heavy(heavy);
for (auto y:a[x])
if (y!=tata[x] && y!=heavy)
dfs_heavy(y);
}
}
void updater(int nod, int st, int dr, int poz, int val)
{
if (st==dr)
aint[nod]=val;
else
{
int mij=(st+dr)/2;
if (poz<=mij)
updater(2*nod,st,mij,poz,val);
else
updater(2*nod+1,mij+1,dr,poz,val);
aint[nod]=max(aint[2*nod],aint[2*nod+1]);
}
}
void update(int poz, int val)
{
updater(1,1,n,poz,val);
}
void update_heavy(int x, int y)
{
update(poz[x],y);
}
int querysolver(int nod, int st, int dr, int left, int right)
{
if (st==left && dr==right)
return aint[nod];
else
{
int mij=(st+dr)/2;
if (right<=mij)
return querysolver(2*nod,st,mij,left,right);
if (left>mij)
return querysolver(2*nod+1,mij+1,dr,left,right);
else
return max(querysolver(2*nod,st,mij,left,mij),querysolver(2*nod+1,mij+1,dr,mij+1,right));
}
}
int query(int st, int dr)
{
return querysolver(1,1,n,st,dr);
}
int query_heavy(int x, int y)
{
int sol;
if (head[x]==head[y])
{
if (niv[x]>niv[y])
swap(x,y);
sol=query(poz[x],poz[y]);
}
else
{
if (niv[head[x]]<niv[head[y]])
swap(x,y);
sol=query(poz[head[x]],poz[x]);
x=tata[head[x]];
sol=max(sol,query_heavy(x,y));
}
return sol;
}
int main()
{ int i,x,y,c;
f>>n>>m;
for (i=1;i<=n;i++)
f>>v[i];
for (i=1;i<n;i++)
{
f>>x>>y;
a[x].push_back(y);
a[y].push_back(x);
}
dfs(1);
for (i=1;i<=n;i++)
head[i]=i;
dfs_heavy(1);
for (i=1;i<=n;i++)
update_heavy(i,v[i]);
for (i=1;i<=m;i++)
{
f>>c>>x>>y;
if (c==0)
update_heavy(x,y);
else
g<<query_heavy(x,y)<<'\n';
}
}