#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5;
const int NIL = 0;
vector <int> g[MAXN + 1], chain[MAXN + 1];
int *arbint[MAXN + 1];
int val[MAXN + 1], father[MAXN + 1], lev[MAXN + 1] = {0, 1}, weight[MAXN + 1], which_chain[MAXN + 1], chain_len[MAXN + 1], pos_in_chain[MAXN + 1];
bool seen[MAXN + 1];
int num_chains;
void decomp_dfs(int node) {
int wmax = NIL;
seen[node] = true;
weight[node] = 1;
for (auto it : g[node])
if (seen[it] == false) {
lev[it] = lev[node] + 1;
father[it] = node;
decomp_dfs(it);
weight[node] += weight[it];
wmax = (weight[it] > weight[wmax]) ? it : wmax;
}
if (wmax == NIL)
which_chain[node] = ++num_chains;
else
which_chain[node] = which_chain[wmax];
chain[which_chain[node]].push_back(node);
}
void build_arbint(int ind, int node, int l, int r) {
if (l == r) {
arbint[ind][node] = val[chain[ind][l - 1]];
return;
}
int mid = (l + r) / 2;
build_arbint(ind, 2 * node, l, mid);
build_arbint(ind, 2 * node + 1, mid + 1, r);
arbint[ind][node] = max(arbint[ind][2 * node], arbint[ind][2 * node + 1]);
}
void update(int ind, int node, int l, int r, int pos, int newv) {
if (l == r) {
arbint[ind][node] = newv;
return;
}
int mid = (l + r) / 2;
if (pos <= mid)
update(ind, 2 * node, l, mid, pos, newv);
else
update(ind, 2 * node + 1, mid + 1, r, pos, newv);
arbint[ind][node] = max(arbint[ind][2 * node], arbint[ind][2 * node + 1]);
}
int query(int ind, int node, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr)
return arbint[ind][node];
int mid = (l + r) / 2, a1 = 0, a2 = 0;
if (ql <= mid)
a1 = query(ind, 2 * node, l, mid, ql, qr);
if (mid < qr)
a2 = query(ind, 2 * node + 1, mid + 1, r, ql, qr);
return max(a1, a2);
}
int heavy_query(int x, int y) {
if (which_chain[x] == which_chain[y]) {
if (pos_in_chain[x] > pos_in_chain[y])
swap(x, y);
return query(which_chain[x], 1, 1, chain_len[which_chain[x]], pos_in_chain[x], pos_in_chain[y]);
}
int ancx = father[chain[which_chain[x]][0]], ancy = father[chain[which_chain[y]][0]];
if (lev[ancx] < lev[ancy]) {
swap(x, y);
swap(ancx, ancy);
}
return max(query(which_chain[x], 1, 1, chain_len[which_chain[x]], 1, pos_in_chain[x]), heavy_query(ancx, y));
}
int main()
{
int n, m, t, x, y;
ifstream fin("heavypath.in");
fin >> n >> m;
for (int i = 1; i <= n; ++i)
fin >> val[i];
for (int i = 1; i < n; ++i) {
fin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
decomp_dfs(1);
which_chain[0] = which_chain[1];
for (int i = 1; i <= num_chains; ++i) {
chain_len[i] = chain[i].size();
reverse(chain[i].begin(), chain[i].end());
for (int j = 0; j < chain_len[i]; ++j)
pos_in_chain[chain[i][j]] = j + 1;
arbint[i] = (int *) malloc(sizeof(int) * (4 * chain_len[i] + 1));
build_arbint(i, 1, 1, chain_len[i]);
}
ofstream fout("heavypath.out");
for (int i = 0; i < m; ++i) {
fin >> t >> x >> y;
if (t == 0)
update(which_chain[x], 1, 1, chain_len[which_chain[x]], pos_in_chain[x], y);
else
fout << heavy_query(x, y) << '\n';
}
fin.close();
fout.close();
return 0;
}