#include <fstream>
#include <vector>
#define DIM 100005
#define INF 2000000005
#define vint vector<int>::iterator
#define infile "heavypath.in"
#define outfile "heavypath.out"
using namespace std;
ifstream f(infile);
ofstream g(outfile);
vector<int> L[DIM], Lant[DIM];
int ap_lant[DIM], Poz[DIM], Niv[DIM], Tlant[DIM], T[DIM], Begin[DIM], Sub[DIM], v[DIM], A[4* DIM];
bool viz[DIM];
int n, m, lanturi, poz, decal, a, b, val, q, x, y, op;
void DFS(int nod, int niv, int parent) {
Niv[nod] = niv;
viz[nod] = 1;
Sub[nod] = 1;
T[nod] = parent;
int Max = 0, mfiu;
for (vint it = L[nod].begin(); it != L[nod].end(); ++it)
if (!viz[*it]) {
DFS(*it, niv + 1, nod);
Sub[nod] += Sub[*it];
if (Sub[*it] > Max) {
Max = Sub[*it];
mfiu = *it;
}
}
if (Max == 0) {
Lant[++lanturi].push_back(nod);
ap_lant[nod] = lanturi;
Tlant[lanturi] = T[nod];
}
else {
Lant[ap_lant[mfiu]].push_back(nod);
ap_lant[nod] = ap_lant[mfiu];
Tlant[ap_lant[mfiu]] = T[nod];
}
}
void update(int nod, int st, int dr) {
if (st == dr && st == poz) {
A[nod + decal] = val;
return;
}
int mid = (st + dr) / 2;
if (mid >= poz)
update(2 * nod, st, mid);
else
update(2 * nod + 1, mid + 1, dr);
A[nod + decal] = max(A[2 * nod + decal], A[2 * nod + 1 + decal]);
}
int query(int nod, int st, int dr) {
if (st >= a && dr <= b)
return A[nod + decal];
int mid = (st + dr) / 2;
int q = 0, Q = 0;
if (a <= mid)
q = query(2 * nod, st, mid);
if (b > mid)
Q = query(2 * nod + 1, mid + 1, dr);
return max(q, Q);
}
int main () {
f >> n >> q;
for (int i = 1; i <= n; ++i)
f >> v[i];
for (int i = 1; i < n; ++i) {
f >> x >> y;
L[x].push_back(y);
L[y].push_back(x);
}
DFS(1, 1, 0);
for (int i = 1; i <= lanturi; ++i) {
Begin[i] = Begin[i - 1] + 4 * Lant[i - 1].size();
int j, k;
for (j = 0, k = Lant[i].size() - 1; j < k; ++j, --k) {
int tmp = Lant[i][j];
Lant[i][j] = Lant[i][k];
Lant[i][k] = tmp;
Poz[Lant[i][j]] = j;
Poz[Lant[i][k]] = k;
}
Poz[Lant[i][j]] = j;
}
for (int i = 1; i <= n; ++i) {
poz = Poz[i];
val = v[i];
decal = Begin[ap_lant[i]];
update(1, 0, Lant[ap_lant[i]].size() - 1);
}
for (; q; --q) {
f >> op >> x >> y;
if (op == 0) {
poz = Poz[x];
val = y;
decal = Begin[ap_lant[x]];
update(1, 0, Lant[ap_lant[x]].size() - 1);
}
else {
int Max = 0;
while (true) {
int l1 = ap_lant[x];
int l2 = ap_lant[y];
if (l1 == l2) {
a = min(Poz[x], Poz[y]);
b = max(Poz[x], Poz[y]);
decal = Begin[l1];
Max = max(Max, query(1, 0, Lant[l1].size() - 1));
break;
}
if (Niv[Tlant[l1]] > Niv[Tlant[l2]]) {
a = 0;
b = Poz[x];
decal = Begin[l1];
Max = max(Max, query(1, 0, Lant[l1].size() - 1));
x = Tlant[l1];
}
else {
a = 0;
b = Poz[y];
decal = Begin[l2];
Max = max(Max, query(1, 0, Lant[l2].size() - 1));
y = Tlant[l2];
}
}
g << Max << "\n";
}
}
return 0;
}
//This room. This bullet. There's a bullet for everyone. And a time. And a place. Yes... maybe this is how it has to be. - 47