#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
const int H = 17;
const int MAX = 1 << H;
int M, N, a, b, t, x, y;
bool heavy[MAX];
int chain[MAX], depth[MAX], parent[MAX], pos[MAX], size[MAX], sorted[MAX],
ST[MAX + MAX], V[MAX];
vector<int> chains[MAX];
vector<int> G[MAX];
struct cmp {
bool operator()(const int & a, const int & b) const {
return depth[a] < depth[b];
}
};
void dfs(int u, int d = 0) {
chain[u] = u;
depth[u] = d;
size[u] = 1;
for (size_t i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (size[v] == 0) {
dfs(v, d + 1);
parent[v] = u;
size[u] += size[v];
}
}
for (size_t i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (parent[v] == u) {
if (2 * size[v] >= size[u]) {
heavy[v] = true;
}
}
}
}
void hld(int u) {
chain[u] = heavy[u] ? chain[parent[u]] : u;
for (size_t i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (parent[v] == u) {
hld(v);
}
}
}
int lca(int a, int b) {
while (chain[a] != chain[b]) {
if (depth[chain[a]] < depth[chain[b]]) {
b = parent[chain[b]];
} else {
a = parent[chain[a]];
}
}
return depth[a] < depth[b] ? a : b;
}
void set(int index, int value) {
ST[index += MAX] = value;
while (index > 1) {
index >>= 1;
ST[index] = max(ST[index << 1], ST[index << 1 | 1]);
}
}
int get(int a, int b, int root = 1, int left = 0, int right = MAX) {
if (left == a && b == right) {
return ST[root];
}
int mid = (left + right) >> 1;
if (b <= mid) {
return get(a, b, root << 1, left, mid);
}
if (mid <= a) {
return get(a, b, root << 1 | 1, mid, right);
}
return max(get(a, mid, root << 1, left, mid),
get(mid, b, root << 1 | 1, mid, right));
}
int query(int x, int y) {
int ans = V[x];
while (x != y) {
if (chain[x] == chain[y]) {
ans = max(ans, get(pos[x], pos[y] + 1));
y = x;
} else {
ans = max(ans, get(pos[chain[y]], pos[y] + 1));
y = parent[chain[y]];
}
}
return ans;
}
int main() {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
scanf("%d", V + i);
}
for (int i = 2; i <= N; i++) {
scanf("%d%d", &a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
dfs(1);
hld(1);
for (int i = 1; i <= N; i++) {
sorted[i] = i;
}
sort(sorted + 1, sorted + 1 + N, cmp());
for (int i = 1; i <= N; i++) {
chains[chain[sorted[i]]].push_back(sorted[i]);
}
for (int i = 1, c = 0; i <= N; i++) {
for (size_t j = 0; j < chains[i].size(); j++) {
pos[chains[i][j]] = c++;
ST[pos[chains[i][j]] + MAX] = V[chains[i][j]];
}
}
for (int i = MAX - 1; i > 0; i--) {
ST[i] = max(ST[i << 1], ST[i << 1 | 1]);
}
for (int i = 1; i <= M; i++) {
scanf("%d%d%d", &t, &x, &y);
if (t == 0) {
V[x] = y;
set(pos[x], y);
}
if (t == 1) {
int p = lca(x, y);
printf("%d\n", max(query(p, x), query(p, y)));
}
}
return 0;
}