#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int DMAX = 100004;
vector <int> A[DMAX], D[DMAX];
int V[DMAX], *aint[DMAX], E[DMAX << 1], I[DMAX], Dp[DMAX << 1], rmq[19][DMAX << 1], l2[DMAX << 1], s = 1, _s, cD[DMAX], cP[DMAX], F[DMAX], lft, rght, pz, _mx;
bool viz[DMAX];
int _max (const int a, const int b) {
return V[a] > V[b] ? a : b;
}
int _min (const int a, const int b) {
return Dp[a] > Dp[b] ? b : a;
}
void DFS (const int nod, const int dep) {
bool k = 1;
viz[nod] = 1;
D[s].push_back (nod);
cD [nod] = s;
cP [nod] = D[s].size ();
E[++_s] = nod;
I[nod] = _s;
Dp[_s] = dep;
rmq[0][_s] = _s;
l2 [_s + 1] = l2 [(_s + 1) >> 1] + 1;
int i;
for (i = 0; i < A[nod].size (); ++i)
if (!viz[A[nod][i]])
F[A[nod][i]] = nod,
DFS (A[nod][i], dep + 1),
k = 0,
E[++_s] = nod,
I[nod] = _s,
Dp[_s] = dep,
rmq[0][_s] = _s,
l2 [_s + 1] = l2 [(_s + 1) >> 1] + 1;
if (k)
++s;
}
void AINT_line_build (const int l, const int r, const int nod) {
if (l == r) {
aint[s][nod] = D[s][l];
return;
}
int m = (l + r) >> 1;
AINT_line_build (l, m, nod * 2);
AINT_line_build (m + 1, r, nod * 2 + 1);
aint[s][nod] = _max (aint[s][nod * 2], aint[s][nod * 2 + 1]);
}
void AINT_build () {
for (--s; s >= 1; --s) {
aint[s] = new int[2 * (D[s].size () + 1)];
AINT_line_build (0, D[s].size () - 1, 1);
}
}
void AINT_query (const int l, const int r, const int nod) {
if (lft <= l && r <= rght) {
if (V[_mx] < V[aint[pz][nod]])
_mx = aint[pz][nod];
return;
}
if (lft > r || rght < l)
return;
int m = (l + r) >> 1;
AINT_query (l, m, nod * 2);
AINT_query (m + 1, r, nod * 2 + 1);
}
void AINT_update (const int l, const int r, const int nod) {
if (l == r)
return;
int m = (l + r) >> 1;
if (lft <= m)
AINT_update (l, m, nod * 2);
else
AINT_update (m + 1, r, nod * 2 + 1);
aint[pz][nod] = _max (aint[pz][nod * 2], aint[pz][nod * 2 + 1]);
}
void RMQ_build () {
int j, l, n;
for (int i = 1; (1 << i) <= _s; ++i)
for (j = 1, n = _s - (1 << i) + 1, l = 1 << i - 1; j <= n; ++j)
rmq[i][j] = _min (rmq[i - 1][j], rmq[i - 1][j + l]);
}
int RMQ_query (const int a, const int b) {
int l = b - a + 1;
return _min (rmq[l2[l]][a], rmq[l2[l]][a + l - (1 << l2[l])]);
}
int query (int nod1, int nod2) { //nod2 father nod1
int mx = 0, k;
while (cD[nod1] != cD[nod2]) {
lft = 1;
rght = cP[nod1];
pz = cD[nod1];
_mx = 0;
AINT_query (1, D[pz].size (), 1);
if (V[_mx] > V[mx])
mx = _mx;
nod1 = F[D[pz][0]];
}
_mx = 0;
lft = cP[nod2];
rght = cP[nod1];
pz = cD[nod1];
AINT_query (1, D[pz].size (), 1);
if (V[_mx] > V[mx])
mx = _mx;
return mx;
}
void update (const int a) {
pz = cD[a];
lft = a;
AINT_update (1, D[pz].size (), 1);
}
int main () {
freopen ("heavypath.in", "r", stdin);
freopen ("heavypath.out", "w", stdout);
int N, M, i, a, b, lca;
bool t;
scanf ("%d%d", &N, &M);
V[0] = -2e9;
for (i = 1; i <= N; ++i)
scanf ("%d", &V[i]);
for (i = 1; i < N; ++i)
scanf ("%d%d", &a, &b),
A[a].push_back (b),
A[b].push_back (a);
DFS (1, 0);
AINT_build ();
RMQ_build ();
// E[RMQ_query (min(I[4], I[7]), max(I[4], I[7]))]
while (M--) {
scanf ("%d%d%d", &t, &a, &b);
if (t) {
if (I[a] > I[b])
swap (a, b);
lca = E[RMQ_query (I[a], I[b])];
printf ("%d\n", V[_max (query (a, lca), query (b, lca))]);
}
else
V[a] = b,
update (a);
}
}