#include <iostream>
#include <fstream>
#include <vector>
const int MAXN = 1e5 + 1;
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
/// nod_lant[i] = in ce lant se afla nodul i
/// pozitie[i] = pe ce pozitie se afla in lantul (deja stiut) nodul i
/// inaltime[i] = care este inaltimea lantului care se afla pe pozitia i
/// daca am lantul pe ex : 4 3 2 1(e luat de la spate in fata din cauza la dfs)
/// atunci nod_lant[4] = nod_lant[3] = nod_lant[2] = nod_lant[1] = 1 primul lant
/// pozitie[4] = 1 in lant se alfa pe poz 1, pozitie[3] = 2, pozitie[2] = 3, pozitie[1] = 4
/// inaltime[1] = 1, se afla la inaltimea 1, dar lantul 9 8 7 se afla la inaltimea 2
/// daca citeste cineva asta sper sa inteleaga :)
/// singurul vector indexat de la 0 este lant[i]
int tata[MAXN],dimensiune[MAXN],nod_lant[MAXN],pozitie[MAXN],inaltime[MAXN];
int valori[MAXN];
bool viz[MAXN];
int nr_lanturi;
vector<int>arbore_intervale[MAXN];/// Sunt indexati de la 1!!!!!
int maxim;/// raspunsul la intrebare
vector<int>lant[MAXN];/// indexati de la 0!!
vector<int>graf[MAXN];
void dfs(int nod,int anterior = -1){
dimensiune[nod] = 1;
viz[nod] = true;
int curent;
for(int i = 0; i < graf[nod].size(); i++){
curent = graf[nod][i];
if(curent == anterior){
/// anteriorul este nodul care a fost parcurs inainte
/// daca eu vreau sa ma duc cu o muchie in spate atunci tatal nodului curent este anterior
tata[nod] = anterior;
}
if(!viz[curent]){
dfs(curent,nod);
dimensiune[nod] += dimensiune[curent];
}
}
if(graf[nod].size() == 1 && nod != 1){
lant[++nr_lanturi].push_back(nod);
nod_lant[nod] = nr_lanturi;
pozitie[nod] = 1; /// il pun pe pozitia 1
}else{
int vecin_bun,maxim = 0;
for(int i = 0; i < graf[nod].size(); i++){
int curent = graf[nod][i];
if(dimensiune[curent] > maxim && curent != anterior){
vecin_bun = curent;
maxim = dimensiune[curent];
}
}
int unde = nod_lant[vecin_bun];
lant[unde].push_back(nod); /// adaug nodul nod la lantul cu subarborele maxim
nod_lant[nod] = unde;
pozitie[nod] = lant[unde].size();/// il pun pe ultima pozitie
}
}
void dfs_inaltimi(int nod){
viz[nod] = true;
for(auto vecin : graf[nod]){
if(!viz[vecin]){
int unde_nod = nod_lant[nod],unde_vecin = nod_lant[vecin];
if(unde_nod != unde_vecin)
inaltime[unde_vecin] = inaltime[unde_nod] + 1;
dfs_inaltimi(vecin);
}
}
}
void update(int index_lant,int val,int pozitie,int st,int dr,int nod = 1){
if(st == dr && st == pozitie){
arbore_intervale[index_lant][nod] = val;
return;
}
int mij = (st + dr) / 2;
if(pozitie <= mij)
update(index_lant,val,pozitie,st,mij,nod * 2);
else
update(index_lant,val,pozitie,mij + 1,dr,nod * 2 + 1);
if(nod * 2 + 1 < arbore_intervale[index_lant].size()) /// sa nu cumva sa ies din size
arbore_intervale[index_lant][nod] = max(arbore_intervale[index_lant][nod * 2],arbore_intervale[index_lant][nod * 2 + 1]);
}
int query(int index_lant,int query_left,int query_right,int st,int dr,int nod = 1){
if(query_left <= st && dr <= query_right)
return arbore_intervale[index_lant][nod];
int mij = (st + dr) / 2;
int val_stanga = 0,val_dreapta = 0;
if(query_left <= mij)
val_stanga = query(index_lant,query_left,query_right,st,mij,nod * 2);
if(mij + 1 <= query_right)
val_dreapta = query(index_lant,query_left,query_right,mij + 1,dr,nod * 2 + 1);
return max(val_stanga,val_dreapta);
}
int query_lant(int nod){
int index_lant = nod_lant[nod];
int dimensiune = lant[index_lant].size();
int poz = pozitie[nod];
return query(index_lant,poz,dimensiune,1,dimensiune);
}
void intrebare(int a,int b){
if(nod_lant[a] == nod_lant[b]){
int index = nod_lant[a];
/// iau maximul de pe lantul a
int mn_poz = min(pozitie[a],pozitie[b]);
int mx_poz = max(pozitie[a],pozitie[b]);
maxim = max(maxim,query(nod_lant[a],mn_poz,mx_poz,1,lant[index].size()));
return;
}
/// vreau h[a] > h[b]
if(inaltime[nod_lant[a]] < inaltime[nod_lant[b]])
swap(a,b);
if(inaltime[nod_lant[a]] > inaltime[nod_lant[b]]){
maxim = max(maxim,query_lant(a));
int sf = lant[nod_lant[a]].back();
intrebare(tata[sf],b);
}else if(inaltime[nod_lant[a]] == inaltime[nod_lant[b]]){
maxim = max(maxim,query_lant(a));
int sf_a = lant[nod_lant[a]].back();
maxim = max(maxim,query_lant(b));
int sf_b = lant[nod_lant[b]].back();
intrebare(tata[sf_a],tata[sf_b]);
}
}
void construieste_arbore(int index_lant){
vector<int>arbore(4 * lant[index_lant].size());
arbore_intervale[index_lant] = arbore;
int lung_lant = lant[index_lant].size();
for(int i = 0; i < lant[index_lant].size(); i++){
int val = valori[lant[index_lant][i]];
update(index_lant,val,i + 1,1,lung_lant);/// !! indexati de la 1 de aia poz = i + 1
}
}
int main()
{
int n,intrebari;
in>>n>>intrebari;
for(int i = 1; i <= n; i++)
in>>valori[i];
for(int i = 1; i <= n - 1; i++){
int x,y;
in>>x>>y;
graf[x].push_back(y);
graf[y].push_back(x);
}
inaltime[1] = 1;
dfs(1);
for(int i = 1; i <= n; i++)
viz[i] = false;
dfs_inaltimi(1);
for(int i = 1; i <= n; i++)
construieste_arbore(i);
for(int i = 1; i <= intrebari; i++){
int cerinta,a,b;
in>>cerinta>>a>>b;
if(cerinta == 1){
maxim = 0;
intrebare(a,b);
out<<maxim<<"\n";
}else{
int index_lant = nod_lant[a];
int pozitie_lant = pozitie[a];
update(index_lant,b,pozitie_lant,1,lant[index_lant].size());
}
}
return 0;
}