#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define PATH(u) paths[pathof[u]]
typedef pair<int, int> II;
vector<int> a;
vector<vector<int>> adjl;
vector<int> parent;
vector<int> level;
vector<int> leaf;
vector<int> pathof;
vector<int> index;
class Path
{
public:
int n;
vector<int> t;
int root;
Path() {}
Path(int leaf, int root, int n) : n(n), root(root)
{
t.resize(2*n);
for (int i = 2*n-1, u = leaf; i >= n; u = parent[u], i--) {
t[i] = a[u];
}
for (int i = n-1; i > 0; i--) {
t[i] = max(t[2*i], t[2*i+1]);
}
// printf("%d\n", n);
// for (int i = 1; i < 2*n; i++) {
// printf("%d ", t[i]);
// }
// puts("");
}
int getmax(int hi)
{
if (hi == n-1) {
return t[1];
}
else {
return getmax(0, hi);
}
}
int getmax(int lo, int hi)
{
lo += n;
hi += n;
int res = 0;
while (lo < hi) {
if (lo & 1) {
res = max(res, t[lo]);
lo >>= 1;
lo++;
}
else {
lo >>= 1;
}
if (hi & 1) {
hi >>= 1;
}
else {
res = max(res, t[hi]);
hi >>= 1;
hi--;
}
}
if (lo == hi) {
res = max(res, t[lo]);
}
return res;
}
void update(int idx, int val)
{
idx += n;
t[idx] = val;
while (idx > 1) {
val = max(t[idx], t[idx^1]);
idx >>= 1;
if (t[idx] == val) {
break;
}
else {
t[idx] = val;
}
}
}
};
vector<Path> paths;
void build_path(int l, int r)
{
int len = 0;
for (int u = l; ; u = parent[u], len++) {
pathof[u] = paths.size();
index[u] = len;
if (u == r) {
len++;
break;
}
}
for (int u = l, i = len-1; i >= 0; u = parent[u], i--) {
index[u] = i;
}
paths.emplace_back(l, r, len);
// puts("asdf");
}
int build_heavy_paths(int u)
{
int size = 1;
if (adjl[u].size() == (u == 0 ? 0 : 1)) {
leaf[u] = u;
}
else {
II heaviest = {0, 0};
for (auto v: adjl[u]) {
if (v == parent[u]) {
continue;
}
parent[v] = u;
level[v] = level[u]+1;
int subsize = build_heavy_paths(v);
size += subsize;
heaviest = max(heaviest, {subsize, v});
}
leaf[u] = leaf[heaviest.second];
for (auto v: adjl[u]) {
if (v == parent[u] || v == heaviest.second) {
continue;
}
else {
build_path(leaf[v], v);
}
}
}
if (u == 0) {
build_path(leaf[u], u);
}
return size;
}
int getmax(int u, int v)
{
int res = 0;
while (pathof[u] != pathof[v]) {
if (level[PATH(u).root] > level[PATH(v).root]) {
swap(u, v);
}
res = max(res, PATH(v).getmax(index[v]));
v = parent[PATH(v).root];
}
II x = minmax(index[u], index[v]);
res = max(res, PATH(v).getmax(x.first, x.second));
return res;
}
void update(int u, int val)
{
PATH(u).update(index[u], val);
}
int main()
{
ios::sync_with_stdio(false);
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int n, m;
cin >> n >> m;
a.resize(n);
for (auto & x: a) {
cin >> x;
}
adjl.resize(n);
for (int i = 0; i < n-1; i++) {
int u, v;
cin >> u >> v;
u--, v--;
adjl[u].push_back(v);
adjl[v].push_back(u);
}
parent.resize(n);
parent[0] = -1;
level.resize(n);
leaf.resize(n);
pathof.resize(n);
index.resize(n);
build_heavy_paths(0);
// for (auto x: leaf) {
// printf("%d ", x);
// }
// puts("");
// for (auto x: level) {
// printf("%d ", x);
// }
// puts("");
// for (auto x: pathof) {
// printf("%d ", x);
// }
// puts("");
// for (auto x: index) {
// printf("%d ", x);
// }
// puts("");
// printf("%d\n", getmax(3, 6));
// printf("%d\n", paths[3].getmax(0, 3));
// printf("%d\n", paths[3].getmax(3));
// printf("%d\n", paths[3].t[1]);
// printf("%d\n", paths[3].n);
// return 0;
for (int i = 0; i < m; i++) {
int op;
cin >> op;
if (op == 0) {
int u, val;
cin >> u >> val;
u--;
update(u, val);
}
else {
int u, v;
cin >> u >> v;
u--, v--;
printf("%d\n", getmax(u, v));
}
}
return 0;
}