#include <fstream>
#include <vector>
#include <algorithm>
const int NMAX=100005;
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
void dfs(int, int);
void heavy_light_decomp();
void build(int, int, int);
void update(int, int, int, int, int);
int query(int, int, int, int, int);
void update_hld(int, int);
int query_hld(int, int);
vector <int> v[NMAX], path[NMAX];
int a[NMAX], poz[NMAX], p[NMAX], aint[NMAX];
int lin[NMAX], sz[NMAX], niv[NMAX], nrp[NMAX];
int pn, n, q;
int main()
{
int i, tip, aa, b;
fin>>n>>q;
for(i=1; i<=n; i++) fin>>a[i];
for(i=1; i<n; i++)
{
fin>>aa>>b;
v[aa].push_back(b);
v[b].push_back(aa);
}
heavy_light_decomp();
for(i=1; i<=q; i++)
{
fin>>tip>>aa>>b;
if(tip==0) update_hld(aa, b);
else fout<<query_hld(aa, b)<<'\n';
}
return 0;
}
void update_hld(int nod, int val)
{
update(1, 1, n, poz[nod], val);
}
int query_hld(int a, int b)
{
int maxim=0;
while(true)
{
if(niv[a]>niv[b]) swap(a, b);
if(nrp[a]==nrp[b])
{
maxim=max(maxim, query(1, 1, n, poz[a], poz[b]));
return maxim;
}
if(niv[path[nrp[a]][0]]>niv[path[nrp[b]][0]]) swap(a, b);
maxim=max(maxim, query(1, 1, n, poz[path[nrp[b]][0]], poz[b]));
b=p[path[nrp[b]][0]];
}
return maxim;
}
void heavy_light_decomp()
{
int i, ind=0;
dfs(1, 1);
for(i=1; i<=pn; i++)
{
reverse(path[i].begin(), path[i].end());
for(auto j:path[i])
{
lin[++ind]=j;
poz[j]=ind;
}
}
build(1, 1, n);
}
void dfs(int nod, int lvl)
{
int maxim=0;
sz[nod]=1; niv[nod]=lvl;
for(auto i:v[nod])
{
if(!sz[i])
{
p[i]=nod;
dfs(i, lvl+1);
if(sz[i]>maxim)
{
maxim=sz[i];
nrp[nod]=nrp[i];
}
sz[nod]+=sz[i];
}
}
if(nrp[nod]==0) nrp[nod]=++pn;
path[nrp[nod]].push_back(nod);
}
void build(int nod, int st, int dr)
{
if(st==dr)
{
aint[nod]=a[lin[st]];
return;
}
int mij=(st+dr)/2;
build(2*nod, st, mij);
build(2*nod+1, mij+1, dr);
aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}
void update(int nod, int st, int dr, int poz, int val)
{
if(st==dr)
{
aint[nod]=val;
return;
}
int mij=(st+dr)/2;
if(poz<=mij) update(2*nod, st, mij, poz, val);
else update(2*nod+1, mij+1, dr, poz, val);
aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}
int query(int nod, int st, int dr, int qst, int qdr)
{
if(st>=qst && dr<=qdr) return aint[nod];
int mij=(st+dr)/2, maxim=0;
if(qst<=mij) maxim=max(maxim, query(2*nod, st, mij, qst, qdr));
if(qdr>mij) maxim=max(maxim, query(2*nod+1, mij+1, dr, qst, qdr));
return maxim;
}