#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int NMAX = 100005;
int n, m;
int v[NMAX];
vector<int> g[NMAX];
int sz[NMAX], par[NMAX], lvl[NMAX];
int head[NMAX], pos[NMAX], chain[NMAX], ptr;
int tree[4 * NMAX], base[NMAX];
void dfs_size(int nod, int p) {
sz[nod] = 1;
par[nod] = p;
for (int i = 0; i < (int)g[nod].size(); ++i) {
int fiu = g[nod][i];
if (fiu != p) {
lvl[fiu] = lvl[nod] + 1;
dfs_size(fiu, nod);
sz[nod] += sz[fiu];
}
}
}
void dfs_hld(int nod, int p, int cap) {
head[nod] = cap;
pos[nod] = ++ptr;
chain[nod] = cap;
int heavy = -1;
for (int i = 0; i < (int)g[nod].size(); ++i) {
int fiu = g[nod][i];
if (fiu != p) {
if (heavy == -1 || sz[fiu] > sz[heavy])
heavy = fiu;
}
}
if (heavy != -1)
dfs_hld(heavy, nod, cap);
for (int i = 0; i < (int)g[nod].size(); ++i) {
int fiu = g[nod][i];
if (fiu != p && fiu != heavy) {
dfs_hld(fiu, nod, fiu);
}
}
}
void build(int nod, int st, int dr) {
if (st == dr) {
tree[nod] = base[st];
return;
}
int mid = (st + dr) / 2;
build(nod * 2, st, mid);
build(nod * 2 + 1, mid + 1, dr);
tree[nod] = max(tree[nod * 2], tree[nod * 2 + 1]);
}
void update(int nod, int st, int dr, int poz, int val) {
if (st == dr) {
tree[nod] = val;
return;
}
int mid = (st + dr) / 2;
if (poz <= mid)
update(nod * 2, st, mid, poz, val);
else
update(nod * 2 + 1, mid + 1, dr, poz, val);
tree[nod] = max(tree[nod * 2], tree[nod * 2 + 1]);
}
int query(int nod, int st, int dr, int l, int r) {
if (l <= st && dr <= r)
return tree[nod];
int mid = (st + dr) / 2;
int ans = -1;
if (l <= mid)
ans = max(ans, query(nod * 2, st, mid, l, r));
if (r > mid)
ans = max(ans, query(nod * 2 + 1, mid + 1, dr, l, r));
return ans;
}
int query_hld(int x, int y) {
int ans = -1;
while (head[x] != head[y]) {
if (lvl[head[x]] < lvl[head[y]])
swap(x, y);
int cap = head[x];
ans = max(ans, query(1, 1, n, pos[cap], pos[x]));
x = par[cap];
}
if (lvl[x] > lvl[y])
swap(x, y);
ans = max(ans, query(1, 1, n, pos[x], pos[y]));
return ans;
}
int main() {
in >> n >> m;
for (int i = 1; i <= n; ++i)
in >> v[i];
for (int i = 1; i < n; ++i) {
int a, b;
in >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
lvl[1] = 1;
dfs_size(1, 0);
ptr = 0;
dfs_hld(1, 0, 1);
for (int i = 1; i <= n; ++i)
base[pos[i]] = v[i];
build(1, 1, n);
for (int i = 1; i <= m; ++i) {
int t, x, y;
in >> t >> x >> y;
if (t == 0) {
update(1, 1, n, pos[x], y);
} else {
out << query_hld(x, y) << '\n';
}
}
return 0;
}