#include <bits/stdc++.h>
using namespace std;
class HLD {
private:
int n, nrPaths = 0, timer = 0;
vector<vector<int>> tree;
vector<int> sz, par, depth, tp, id;
class Segtree {
private:
vector<int> tree;
public:
void init(int sz) {
tree.resize(3 * sz);
}
void update(int node, int l, int r, int pos, int val) {
if (l == r) {
tree[node] = val;
return;
}
int mid = (l + r) / 2;
if (pos <= mid) { update(2 * node, l, mid, pos, val); }
else { update(2 * node + 1, mid + 1, r, pos, val); }
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int l, int r, int x, int y) {
if (r < x || l > y) { return 0; }
if (x <= l && r <= y) { return tree[node]; }
int mid = (l + r) / 2;
int left = query(2 * node, l, mid, x, y);
int right = query(2 * node + 1, mid + 1, r, x, y);
return max(left, right);
}
}st;
public:
HLD(const vector<vector<int>> &g) {
tree = g;
n = (int)tree.size() - 1;
sz.resize((int)tree.size());
par.resize((int)tree.size());
depth.resize((int)tree.size());
tp.resize((int)tree.size());
id.resize((int)tree.size());
st.init((int)tree.size());
dfs(1, 1);
decompose(1, 1, 1);
for (int i = 1; i <= n; i++) { cout << tp[i] << ' '; }
}
void dfs(int node, int parent) {
sz[node] = 1;
par[node] = parent;
for (int son : tree[node]) {
if (son == parent) { continue; }
depth[son] = depth[node] + 1;
dfs(son, node);
sz[node] += sz[son];
}
}
void decompose(int node, int parent, int top) {
id[node] = ++timer;
tp[node] = top;
pair<int, int> child = {-1, -1};
for (int son : tree[node]) {
if (son == parent) { continue; }
if (sz[son] > child.second) {
child.first = son;
child.second = sz[son];
}
}
if (child.first == -1) { return; }
decompose(child.first, node, top);
for (int son : tree[node]) {
if (son == parent || son == child.first) { continue; }
decompose(son, node, son);
}
}
void update(int idx, int val) {
st.update(1, 1, n, id[idx], val);
}
int query(int x, int y) {
int ans = 0;
while (tp[x] != tp[y]) {
if (depth[tp[x]] < depth[tp[y]]) { swap(x, y); }
ans = max(ans, st.query(1, 1, n, id[tp[x]], id[x]));
x = par[tp[x]];
}
if (depth[x] > depth[y]) { swap(x, y); }
ans = max(ans, st.query(1, 1, n, id[x], id[y]));
return ans;
}
};
int main() {
ifstream in("heavypath.in");
ofstream out("heavypath.out");
int n, q;
in >> n >> q;
vector<int> val(n + 1);
for (int i = 1; i <= n; i++) {
in >> val[i];
}
vector<vector<int>> tree(n + 1);
for (int i = 1; i < n; i++) {
int x, y;
in >> x >> y;
tree[x].push_back(y);
tree[y].push_back(x);
}
HLD hld(tree);
for (int i = 1; i <= n; i++) {
hld.update(i, val[i]);
}
while (q--) {
int type, x, y;
in >> type >> x >> y;
if (type == 0) {
hld.update(x, y);
} else {
out << hld.query(x, y) << "\n";
}
}
return 0;
}