#include <fstream>
#include <vector>
using namespace std;
const int Nmax = 100005;
int n, m, sol;
int numar_lanturi;
struct arbore{
int val;
int nivel;
int indice_lant;
int pozitie_aint;
int greutate;
vector<int> sons;
};
struct heavy{
vector<int> lant;
vector<int> aint;
int parinte = 0;
void build_aint(int nod, int st, int dr){
if(st == dr){
aint[nod] = lant[st];
return;
}
int mid = (st + dr) / 2;
build_aint(2 * nod, st, mid);
build_aint(2 * nod + 1, mid + 1, dr);
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void update_aint(int nod, int st, int dr, int poz, int val){
if(st == dr && st == poz){
aint[nod] = val;
return;
}
int mid = (st + dr) / 2;
if(poz <= mid){
update_aint(2 * nod, st, mid, poz, val);
}
else{
update_aint(2 * nod + 1, mid + 1, dr, poz, val);
}
aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
int query_aint(int nod, int st, int dr, int a, int b){
if(st == a && dr == b){
return aint[nod];
}
int mid = (st + dr) / 2;
if(b <= mid){
return query_aint(2 * nod, st, mid, a, b);
}
else if(mid < a){
return query_aint(2 * nod + 1, mid + 1, dr, a, b);
}
else{
return max(query_aint(2 * nod, st, mid, a, mid), query_aint(2 * nod + 1, mid + 1, dr, mid + 1, b));
}
}
};
arbore arb[Nmax];
heavy lanturi[Nmax];
void build_heavy(int nod, int nivel){
arb[nod].nivel = nivel;
if(arb[nod].sons.size() == 0){
lanturi[++numar_lanturi].lant.push_back(arb[nod].val);
arb[nod].greutate = 1;
arb[nod].indice_lant = numar_lanturi;
arb[nod].pozitie_aint = 0;
return;
}
int greutate_max = 0, indice = -1;
for(int son : arb[nod].sons){
build_heavy(son, nivel + 1);
if(arb[son].greutate > greutate_max){
indice = son;
greutate_max = arb[son].greutate;
}
}
arb[nod].greutate = 1;
for(int son : arb[nod].sons){
arb[nod].greutate += arb[son].greutate;
if(son != indice){
lanturi[arb[son].indice_lant].parinte = nod;
}
else{
lanturi[arb[son].indice_lant].lant.push_back(arb[nod].val);
arb[nod].indice_lant = arb[son].indice_lant;
arb[nod].pozitie_aint = lanturi[arb[son].indice_lant].lant.size() - 1;
}
}
}
void build_lanturi(){
for(int i = 1; i <= numar_lanturi; i++){
lanturi[i].aint.resize(4 * lanturi[i].lant.size());
lanturi[i].build_aint(1, 0, lanturi[i].lant.size() - 1);
}
}
void query(int a, int b){
if(arb[a].indice_lant == arb[b].indice_lant){
sol = max(sol, lanturi[arb[a].indice_lant].query_aint(1, 0, lanturi[arb[a].indice_lant].lant.size() - 1, min(arb[a].pozitie_aint, arb[b].pozitie_aint), max(arb[a].pozitie_aint, arb[b].pozitie_aint)));
return;
}
if(arb[lanturi[arb[a].indice_lant].parinte].nivel < arb[lanturi[arb[b].indice_lant].parinte].nivel){
swap(a, b);
}
sol = max(sol, lanturi[arb[a].indice_lant].query_aint(1, 0, lanturi[arb[a].indice_lant].lant.size() - 1, arb[a].pozitie_aint, lanturi[arb[a].indice_lant].lant.size() - 1));
query(lanturi[arb[a].indice_lant].parinte, b);
}
int main()
{
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int a, b, poz, val;
bool type;
fin >> n >> m;
for(int i = 1; i <= n; i++){
fin >> arb[i].val;
}
for(int i = 1; i <= n - 1; i++){
fin >> a >> b;
if(a > b){
swap(a, b);
}
arb[a].sons.push_back(b);
}
numar_lanturi = 0;
build_heavy(1, 1);
build_lanturi();
for(int i = 1; i <= m; i++){
fin >> type;
if(type){
fin >> a >> b;
sol = 0;
query(a, b);
fout << sol << '\n';
}
else{
fin >> poz >> val;
arb[poz].val = val;
lanturi[arb[poz].indice_lant].update_aint(1, 0, lanturi[arb[poz].indice_lant].lant.size() - 1, arb[poz].pozitie_aint, val);
}
}
return 0;
}