#include <bits/stdc++.h>
using namespace std;
template <typename T> class Segtree {
public:
int n, k; vector <T> t; T neutral;
function <T (T, T)> f;
Segtree(int n, T neu, function <T (T, T)> _f) : n(n), k(0), t(2 * n, neu), neutral(neu), f(_f) {}
void push(T val) { t[n + (k++)] = val; }
void build() {
for(int i = n - 1; i > 0; i--)
t[i] = f(t[i << 1], t[i << 1 | 1]);
}
void update(int pos, T val) {for(t[pos += n] = val; pos > 1; pos >>= 1) t[pos >> 1] = f(t[pos], t[pos ^ 1]);}
T query(int l, int r) { /// on interval [l, r), indexed from 0
T resl(neutral), resr(neutral);
for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
if(l & 1) resl = f(resl, t[l++]);
if(r & 1) resr = f(t[--r], resr);
}
return f(resl, resr);
}
};
template <typename T>
class HeavyLight {
int n, timer;
vector <vector <int>>& g;
vector <int> sz, head, par, link, h, tin, lg2, rev;
vector <vector <int>> e;
vector <T> val;
function <T(T, T)> f; T neutral;
vector <Segtree <T>> HP;
void decompose(int u, int p) {
par[u] = p;
sz[u] = 1;
int mx = 0;
tin[u] = ++timer;
rev[tin[u]] = u;
e[tin[u]][0] = tin[u];
for(int v : g[u]) if(v != p) {
decompose(v, u);
sz[u] += sz[v];
if(sz[v] > sz[mx])
mx = v;
}
link[u] = mx;
h[u] = h[link[u]] + 1;
head[mx] = u;
e[++timer][0] = tin[p];
}
void build(int u) {
int v = link[u];
if(!head[u]) {
HP.emplace_back(h[u], neutral, f);
h[u] = 0;
head[u] = u;
link[u] = HP.size() - 1;
} else {
h[u] = h[head[u]] + 1;
link[u] = link[head[u]];
head[u] = head[head[u]];
}
HP[link[u]].push(val[u]);
if(v) build(v);
if(head[u] == u)
HP[link[u]].build();
}
int LCA(int x, int y) {
x = tin[x], y = tin[y];
if(x > y) swap(x, y);
int l = lg2[y - x + 1];
return rev[min(e[x][l], e[y - (1 << l) + 1][l])];
}
public:
template <typename Iterator>
HeavyLight(vector <vector <int>>& _g, Iterator first, Iterator last, auto _f, T neut) : n(last - first), timer(0), g(_g), val(n + 1), sz(n + 1, 0),
head(n + 1, 0), par(n + 1, 0), link(n + 1, 0), h(n + 1, 0), tin(n + 1, 0), lg2(2 * n + 1, 0), e(2 * n + 1), rev(2 * n + 1, 0), f(_f), neutral(neut) {
int l = 32 - __builtin_clz(n);
for(int i = 1; i <= 2 * n; i++) e[i].resize(l, 0);
for(int i = 2; i <= 2 * n; i++)
lg2[i] = lg2[i >> 1] + 1;
for(auto it = first; it != last; it++)
val[it - first + 1] = *it;
decompose(1, 0);
for(int j = 1; j <= l; j++)
for(int i = 1; i <= 2 * n; i++)
if(i + (1 << j) <= 2 * n)
e[i][j] = min(e[i][j - 1], e[i + (1 << j - 1)][j - 1]);
for(int i = 1; i <= n; i++) if(!head[i])
build(i);
}
void update(int x, T y) {
HP[link[x]].update(h[x], y);
}
T query_vertical(int x, int r) {
if(x == r) return neutral;
if(head[x] == head[r]) return HP[link[x]].query(h[r] + 1, h[x] + 1);
return f(HP[link[x]].query(0, h[x] + 1), query_vertical(par[head[x]], r));
}
T query(int x, int y) {
int lca = LCA(x, y);
return f(f(query_vertical(x, lca), query_vertical(y, lca)), HP[link[lca]].query(h[lca], h[lca] + 1));
}
};
const int N = 1e5;
vector <vector <int>> g;
int val[N + 5];
int main()
{
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
int n, m, u, v;
cin >> n >> m;
g.resize(n + 1);
for(int i = 1; i <= n; i++)
cin >> val[i];
for(int i = 1; i < n; i++)
cin >> u >> v,
g[u].push_back(v),
g[v].push_back(u);
HeavyLight <int> HLD(g, val + 1, val + n + 1, [](int a, int b){ return max(a, b); }, 0);
for(int i = 1; i <= m; i++) {
int t, x, y;
cin >> t >> x >> y;
if(t == 0) HLD.update(x, y);
else cout << HLD.query(x, y) << "\n";
}
return 0;
}