#include <fstream>
#include <vector>
#include <algorithm>
#include <iostream>
const int LOG=17;
const int NMAX=100005;
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector <int> v[NMAX], path;
int val[NMAX], poz[NMAX], sz[NMAX], pth[NMAX];
int niv[NMAX], w[NMAX], hv[NMAX];
int t[NMAX], aint[4*NMAX];
int n, q, nrp, cnt;
void build(int, int, int);
void update(int, int, int, int, int);
int query(int, int, int, int, int);
void build_lca();
void dfs1(int);
bool is_anc(int, int);
int lca(int, int);
void dfs2(int, int);
void decomp();
void ord();
int query_hpd(int, int);
void update_hpd(int, int);
int qrry(int, int);
bool cmp(int a, int b)
{
if(niv[a]==niv[b]) return a<b;
return niv[a]<niv[b];
}
int main()
{
int i, tip, a, b;
fin>>n>>q;
for(i=1; i<=n; i++) fin>>w[i];
for(i=1; i<n; i++)
{
fin>>a>>b;
v[a].push_back(b);
v[b].push_back(a);
}
t[1]=1;
dfs2(1, 1);
decomp();
ord();
for(i=1; i<=q; i++)
{
fin>>tip>>a>>b;
if(tip==0) update_hpd(a, b);
else fout<<query_hpd(a, b)<<'\n';
}
return 0;
}
void update_hpd(int nod, int val)
{
update(1, 1, n, poz[nod], val);
}
int query_hpd(int a, int b)
{
int maxim=0;
while(true)
{
if(pth[a]==pth[b])
{
maxim=max(maxim, query(1, 1, n, poz[a], poz[b]));
break;
}
if(niv[a]>niv[b]) swap(a, b);
maxim=max(maxim, query(1, 1, n, poz[path[pth[b]]], poz[b]));
b=t[path[pth[b]]];
}
return maxim;
}
void ord()
{
int i, nr=0;
for(i=1; i<=n; i++) val[poz[i]]=w[i];
build(1, 1, n);
}
void decomp()
{
int nod, i, cnt=0;
path.push_back(0);
for(i=1; i<=n; i++) val[i]=i;
sort(val+1, val+n+1, cmp);
for(i=1; i<=n; i++)
{
if(!pth[val[i]])
{
++nrp;
nod=val[i];
path.push_back(nod);
while(true)
{
//l-am adaugat in path-ul nrp
pth[nod]=nrp;
poz[nod]=++cnt;
if(hv[nod]==0) break;
nod=hv[nod];
}
}
}
}
void dfs2(int nod, int lvl)
{
sz[nod]=1;
niv[nod]=lvl;
for(auto i:v[nod])
{
if(!sz[i])
{
t[i]=nod;
dfs2(i, lvl+1);
sz[nod]+=sz[i];
if(sz[hv[nod]]<sz[i]) hv[nod]=i;
}
}
v[nod].clear();
}
void build(int nod, int st, int dr)
{
if(st==dr)
{
aint[nod]=val[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;
}