#include <bits/stdc++.h>
using namespace std;
const int nmx = 100002;
int n,m;
vector <int> g[nmx],aux;
vector <vector<int> > lant,arb;
int tata_lant[nmx];
int greutate[nmx],val[nmx],care_lant[nmx],poz_lant[nmx],nivel[nmx];
void citire()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &val[i]);
int nod1,nod2;
for(int i = 1; i < n; ++i)
{
scanf("%d %d", &nod1, &nod2);
g[nod1].push_back(nod2);
g[nod2].push_back(nod1);
}
}
void dfs(int nod, int tata)
{
int maxim = -1, urm_nod = -1;
greutate[nod] = 1;
nivel[nod] = nivel[tata] + 1;
for(vector<int>::iterator it = g[nod].begin(); it != g[nod].end(); ++it)
if(*it != tata)
{
dfs(*it,nod);
greutate[nod] += greutate[*it];
if(greutate[*it] > maxim)
{
maxim = greutate[*it];
urm_nod = *it;
}
tata_lant[care_lant[*it]] = nod;
}
if(maxim == -1)
{
aux.clear();
aux.push_back(nod);
lant.push_back(aux);
care_lant[nod] = lant.size()-1;
}
else
{
lant[care_lant[urm_nod]].push_back(nod);
care_lant[nod] = care_lant[urm_nod];
}
}
void aranjare_lanturi()
{
for(size_t i = 0; i < lant.size(); ++i)
reverse(lant[i].begin(),lant[i].end());
}
int int_st, int_dr, nr_lant, val_schimb, pozitie, max_cautat;
void update(int st, int dr, int nod)
{
if(st == dr)
{
arb[nr_lant][nod] = val_schimb;
return;
}
int mij = (st + dr) / 2;
if(pozitie <= mij)
update(st,mij,2*nod);
else
update(mij+1,dr,2*nod+1);
arb[nr_lant][nod] = max(arb[nr_lant][2*nod],arb[nr_lant][2*nod+1]);
}
void query(int st, int dr, int nod)
{
if(int_st <= st && int_dr >= dr)
{
max_cautat = max(max_cautat,arb[nr_lant][nod]);
return;
}
int mij = (st + dr) / 2;
if(int_st <= mij)
query(st,mij,2*nod);
if(int_dr > mij)
query(mij+1,dr,2*nod+1);
}
void arbori_intervale()
{
for(size_t i = 0; i < lant.size(); ++i)
{
arb.push_back(aux);
arb[i].resize(lant[i].size() * 4 + 2,0);
nr_lant = i;
for(size_t j = 0; j < lant[i].size(); ++j)
{
poz_lant[lant[i][j]] = j + 1;
val_schimb = val[lant[i][j]];
pozitie = poz_lant[lant[i][j]];
update(1,lant[i].size(),1);
}
}
}
void cautare(int nod1, int nod2)
{
max_cautat = -1;
while(care_lant[nod1] != care_lant[nod2])
{
if(nivel[nod1] < nivel[nod2])
{
int_st = 1;
int_dr = poz_lant[nod2];
nr_lant = care_lant[nod2];
query(1,lant[care_lant[nod2]].size(),1);
nod2 = tata_lant[care_lant[nod2]];
}
else
{
int_st = 1;
int_dr = poz_lant[nod1];
nr_lant = care_lant[nod1];
query(1,lant[care_lant[nod1]].size(),1);
nod1 = tata_lant[care_lant[nod1]];
}
}
int_st = min(poz_lant[nod1],poz_lant[nod2]);
int_dr = max(poz_lant[nod1],poz_lant[nod2]);
nr_lant = care_lant[nod1];
query(1,lant[care_lant[nod1]].size(),1);
}
void operatii()
{
int op,x,y;
for(int i = 1; i <= m; ++i)
{
scanf("%d %d %d", &op, &x, &y);
if(op == 0)
{
pozitie = poz_lant[x];
val_schimb = y;
nr_lant = care_lant[x];
update(1,lant[nr_lant].size(),1);
}
else
{
cautare(x,y);
printf("%d\n", max_cautat);
}
}
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
citire();
dfs(1,0);
tata_lant[care_lant[1]] = 0;
aranjare_lanturi();
arbori_intervale();
//for(int i = 0; i < 4; ++i)
// printf("%d ", tata_lant[i]);
operatii();
return 0;
}