#include <bits/stdc++.h>
#define f first
#define s second
#define pb push_back
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
int n, m, x, y, t, nr, ianstefancazacu;
vector <int> v[100005];
int a[100005];
struct noddeaint{
int s, d, v;
};
noddeaint aux;
struct lant{
vector <int> d;
int pnod, nr;
vector <noddeaint> aint;
};
pair <int, int> pl[100005];
bool viz[100005];
lant l[100005];
int deep[100005];
int rmq[100005][18];
void dfs(int nod){
viz[nod] = 1;
//cout << nod << " " << deep[nod] << "\n";
if((v[nod].size() == 1 && nod != 1) || v[nod].size() == 0){
nr++;
l[nr].d.pb(nod);
l[nr].aint.pb(aux);
pl[nod].f = nr;
pl[nod].s = 0;
}
else{
int maxim = 0, pmax, cop;
for(int i = 0; i < v[nod].size(); i++){
cop = v[nod][i];
if(viz[cop] == 0){
deep[cop] = deep[nod] + 1;
dfs(cop);
rmq[cop][0] = nod;
if(l[pl[cop].f].d.size() > maxim){
maxim = l[pl[cop].f].d.size();
pmax = cop;
}
}
}
l[pl[pmax].f].d.pb(nod);
pl[nod].f = pl[pmax].f;
pl[nod].s = pl[pmax].s + 1;
for(int i = 0; i < v[nod].size(); i++){
cop = v[nod][i];
if(cop != pmax){
l[pl[cop].f].pnod = nod;
}
}
}
}
void build(int p, int ind){
int st = l[ind].aint[p].s, dr = l[ind].aint[p].d;
if(st == dr){
if(st < l[ind].d.size()){
l[ind].aint[p].v = a[l[ind].d[st]];
}
else{
l[ind].aint[p].v = 0;
}
}
else{
l[ind].aint[p*2].s = st;
l[ind].aint[p*2].d = (st + dr) / 2;
l[ind].aint[p*2+1].s = (st + dr) / 2 + 1;
l[ind].aint[p*2+1].d = dr;
build(p * 2, ind);
build(p * 2 + 1, ind);
l[ind].aint[p].v = max(l[ind].aint[p*2].v, l[ind].aint[p*2+1].v);
}
//cout << ind << " " << p << " " << st << " " << dr << " " << l[ind].aint[p].v << "\n";
}
void upd(int ind, int p, int poz, int u){
int st = l[ind].aint[p].s, dr = l[ind].aint[p].d;
if(st <= poz && dr >= poz){
if(st == dr){
l[ind].aint[p].v = u;
}
else{
upd(ind, p * 2, poz, u);
upd(ind, p * 2 + 1, poz, u);
l[ind].aint[p].v = max(l[ind].aint[p*2].v, l[ind].aint[p*2+1].v);
}
}
}
int query(int ind, int p, int s, int d){
int st = l[ind].aint[p].s, dr = l[ind].aint[p].d;
if(st >= s && dr <= d){
return l[ind].aint[p].v;
}
else if(dr < s || st > d){
return -1;
}
else{
return max(query(ind, p * 2, s, d), query(ind, p * 2 + 1, s, d));
}
}
void niggers(){
for(int i = 1; i <= 16; i++){
for(int j = 1; j <= n; j++){
rmq[j][i] = rmq[rmq[j][i-1]][i-1];
//cout << i << " " << j << " " << rmq[j][i] << "\n";
}
}
}
int queryrmq(int nod, int depth){
//cout << nod << " ";
if(deep[nod] == depth){
return nod;
}
else{
int p = 0;
while(deep[rmq[nod][p+1]] >= depth){
p++;
}
return queryrmq(rmq[nod][p], depth);
}
}
int lca(int u, int v){
int st = 1;
int dr = min(deep[u], deep[v]);
int mij, rez;
while(st <= dr){
mij = (st + dr) / 2;
//cout << mij << " ";
if(queryrmq(u, mij) == queryrmq(v, mij)){
rez = mij;
st = mij + 1;
}
else{
dr = mij - 1;
}
}
return queryrmq(u, rez);
}
int queryreal(int nod, int unde){
//cout << nod << " ";
if(pl[nod].f == pl[unde].f){
return query(pl[nod].f, 1, pl[nod].s, pl[unde].s);
}
else{
return max(query(pl[nod].f, 1, pl[nod].s, l[pl[nod].f].d.size() - 1), queryreal(l[pl[nod].f].pnod, unde));
}
}
void solve(){
fin >> n >> m;
for(int i = 1; i <= n; i++){
fin >> a[i];
}
for(int i = 1; i < n; i++){
fin >> x >> y;
v[x].pb(y);
v[y].pb(x);
}
deep[1] = 1;
dfs(1);
for(int i = 1; i <= nr; i++){
l[i].nr = 1;
for(int j = 0; j < l[i].d.size(); j++){
//cout << l[i].d[j] << " ";
}
while(l[i].nr < l[i].d.size()){
l[i].nr *= 2;
}
//cout << "\n" << l[i].nr << "\n";
l[i].aint.resize(l[i].nr * 2);
l[i].aint[1].s = 0;
l[i].aint[1].d = l[i].nr - 1;
build(1, i);
}
niggers();
while(m--){
fin >> t >> x >> y;
if(t == 0){
upd(pl[x].f, 1, pl[x].s, y);
}
else{
ianstefancazacu = lca(x, y);
//cout << ianstefancazacu << "\n";
fout << max(queryreal(x, ianstefancazacu), queryreal(y, ianstefancazacu)) << "\n";
//cout << "\n";
}
}
}
int main()
{
solve();
return 0;
}