#include <algorithm>
#include <cstdio>
#include <vector>
const int MAX_N = 100000;
std::vector<int> neighbours[1 + MAX_N];
std::vector<int> heavyTraversal;
int position[1 + MAX_N], Size[1 + MAX_N], heavySon[1 + MAX_N], chainId[1 + MAX_N], chainCount;
int val[1 + MAX_N], ArbInt[4 * MAX_N], N;
bool visited[1 + MAX_N];
struct Chain {
int head;
int master;
int headDepth;
};
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 sol = 0;
if (begin <= mid)
sol = std::max(sol, query(2 * nod, st, mid, begin, end));
if (mid < end)
sol = std::max(sol, query(2 * nod + 1, mid + 1, dr, begin, end));
return sol;
}
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].master = u;
chains[chainCount].headDepth = 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]].headDepth > chains[chainId[u]].headDepth)
std::swap(u, v);
return std::max(maxPath(chains[chainId[u]].master, v),
query(position[chains[chainId[u]].head], position[u]));
}
}
int updateAdd(int u, int add) {
update(position[u], add);
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int Q;
scanf("%d%d", &N, &Q);
for (int i = 1; i <= N; i++)
scanf("%d", &val[i]);
for (int i = 1; i < N; i++) {
int x, y;
scanf("%d%d", &x, &y);
neighbours[x].push_back(y);
neighbours[y].push_back(x);
}
Size[0] = 0;
dfsSize(1);
for (int i = 1; i <= N; i++)
visited[i] = false;
chainCount = 0;
chains[chainCount].master = 0;
chains[chainCount].headDepth = 1;
chains[chainCount].head = 1;
chainCount++;
dfsHeavy(1, 1);
int j = 0;
for (int i : heavyTraversal) {
j++;
updateAdd(j, i);
}
for (int i = 1; i <= Q; i++) {
int x, y, q;
scanf("%d%d%d", &q, &x, &y);
if (q == 0)
updateAdd(x, y);
else
printf("%d\n", maxPath(x, y));
}
return 0;
}