#include <bits/stdc++.h>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int n,m,v[100005];
int poz[100005],l[100005],w[100005],lvl[100005],t[100005],c[100005],Max[100005];
int cnt,paths = 1;
vector<int> G[100005];
int ai[500005];
void get_w(int nod, int from = 0)
{
w[nod] = 1;
for(auto it : G[nod])
{
if(it==from)
{
continue;
}
get_w(it,nod);
w[nod]+=w[it];
if(w[it]>w[Max[nod]])
{
Max[nod] = it;
}
}
}
void get_paths(int nod, int from = 0, int level = 1)
{
poz[nod] = (++cnt);
l[nod] = paths;
if(G[nod].size()==1 && nod!=1)
{
return;
}
get_paths(Max[nod],nod,level+1);
for(auto it : G[nod])
{
if(it==from || it==Max[nod])
{
continue;
}
++paths;
c[paths] = it;
t[paths] = nod;
lvl[paths] = level+1;
get_paths(it,nod,level+1);
}
}
void update(int poz, int val, int nod, int a, int b)
{
if(a==b)
{
ai[nod] = val;
return;
}
int mij = (a+b)>>1;
if(poz<=mij)
{
update(poz,val,nod*2,a,mij);
}
else
{
update(poz,val,nod*2+1,mij+1,b);
}
ai[nod] = max(ai[nod*2],ai[nod*2+1]);
}
int query(int qa, int qb, int nod, int a, int b)
{
if(qa<=a && qb>=b)
{
return ai[nod];
}
int mij = (a+b)>>1;
int rez1 = 0, rez2 = 0;
if(qa<=mij)
{
rez1 = query(qa,qb,nod*2,a,mij);
}
if(qb>mij)
{
rez2 = query(qa,qb,nod*2+1,mij+1,b);
}
return max(rez1,rez2);
}
int query_arb(int x,int y)
{
int rez = 0;
while(l[x]!=l[y])
{
if(lvl[l[y]]>lvl[l[x]])
{
swap(x,y);
}
rez = max(rez,query(poz[c[l[x]]],poz[x],1,1,n));
x = t[l[x]];
}
if(poz[x]>poz[y])
{
swap(x,y);
}
rez = max(rez,query(poz[x],poz[y],1,1,n));
return rez;
}
int main()
{
f>>n>>m;
for(int i=1;i<=n;i++)
{
f>>v[i];
}
for(int i=1;i<n;i++)
{
int x,y;
f>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
get_w(1);
lvl[1] = 1;
c[1] = 1;
get_paths(1);
for(int i=1;i<=n;i++)
{
update(poz[i],v[i],1,1,n);
}
for(int i=1;i<=m;i++)
{
int t;
f>>t;
if(t==0)
{
int nod,val;
f>>nod>>val;
update(poz[nod],val,1,1,n);
}
else if(t==1)
{
int x,y;
f>>x>>y;
g<<query_arb(x,y)<<'\n';
}
}
return 0;
}