#include <stdio.h>
#include <vector>
const int MAX_N = 100000;
int N, Q;
std::vector<int> neighbours[1 + MAX_N];
std::vector<int> heavyTraversal;
int position[1 + MAX_N], heavySon[1 + MAX_N], Size[1 + MAX_N];
bool visited[1 + MAX_N];
int ArbInt[4 * MAX_N], val[1 + MAX_N];
struct Chain {
int head;
int father;
int fatherDepth;
};
int chainId[1 + MAX_N];
int chainCount;
Chain chains[MAX_N];
void update(int nod, int st, int dr, int i, int val) {
if (st == dr) {
ArbInt[nod] = val;
} else {
int mid = (st + dr) / 2;
if (i <= mid)
update(2 * nod, st, mid, i, val);
else
update(2 * nod + 1, mid + 1, dr, i, val);
ArbInt[nod] = std::max(ArbInt[2 * nod], ArbInt[2 * nod + 1]);
}
}
void update(int i, int val) {
update(1, 1, N, i, val);
}
int query(int nod, int st, int dr, int begin, int end) {
if (begin <= st && dr <= end)
return ArbInt[nod];
int mid = (st + dr) / 2;
int ans = 0;
if (begin <= mid)
ans = std::max(ans, query(2 * nod, st, mid, begin, end));
if (mid < end)
ans = std::max(ans, query(2 * nod + 1, mid + 1, dr, begin, end));
return ans;
}
int query(int begin, int end) {
return query(1, 1, N, begin, end);
}
void dfsSize(int u) {
visited[u] = true;
Size[u] = 1;
for (int v : neighbours[u]) {
if (!visited[v]) {
dfsSize(v);
Size[u] += Size[v];
if (Size[heavySon[u]] < Size[v])
heavySon[u] = v;
}
}
}
void dfsHeavy(int u, int depthU) {
visited[u] = true;
heavyTraversal.push_back(val[u]);
position[u] = heavyTraversal.size();
chainId[u] = chainCount;
if (heavySon[u] != 0) {
dfsHeavy(heavySon[u], depthU + 1);
for (int v : neighbours[u])
if (v != heavySon[u] && !visited[v]) {
chainCount++;
chains[chainCount].father = u;
chains[chainCount].fatherDepth = depthU;
chains[chainCount].head = v;
dfsHeavy(v, depthU + 1);
}
}
}
int maxPath(int u, int v) {
if (chainId[u] == chainId[v]) {
if (position[u] < position[v])
return query(position[u], position[v]);
else
return query(position[v], position[u]);
} else {
if (chains[chainId[v]].fatherDepth > chains[chainId[u]].fatherDepth)
std::swap(u, v);
int ans1 = maxPath(chains[chainId[u]].father, v);
int ans2 = query(position[chains[chainId[u]].head], position[u]);
return std::max(ans1, ans2);
}
}
void updateNode(int u, int add) {
update(position[u], add);
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d%d", &N, &Q);
for (int i = 1; i <= N; i++)
scanf("%d", &val[i]);
for (int i = 1; i < N; i++) {
int u, v;
scanf("%d%d", &u, &v);
neighbours[u].push_back(v);
neighbours[v].push_back(u);
}
Size[0] = 0;
dfsSize(1);
for (int i = 1; i <= N; i++)
visited[i] = false;
chainCount = 1;
chains[chainCount].father = 0;
chains[chainCount].fatherDepth = 0;
chains[chainCount].head = 1;
dfsHeavy(1, 1);
int j = 0;
for (int i : heavyTraversal)
update(++j, i);
for (int i = 1; i <= Q; i++) {
int q, x, y;
scanf("%d%d%d", &q, &x, &y);
if (q == 0) {
updateNode(x, y);
} else if (q == 1) {
printf("%d\n", maxPath(x, y));
}
}
fclose(stdin);
fclose(stdout);
return 0;
}