#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
{
int n;
vector<int> t0;
vector<int> t1;
public:
int root;
Path() {}
Path(int leaf, int root, int n) : n(n), root(root)
{
t0.resize(n+1);
t1.resize(n+1);
for (int i = n, u = leaf; i >= 1; u = parent[u], i--) {
t1[i] = a[u];
}
for (int stp = 2; stp <= n; stp *= 2) {
for (int i = stp; i <= n; i += stp) {
t0[i-stp/2] = t0[i];
t1[i] = max(t1[i-stp/2], t1[i]);
}
}
}
int getmax(int lo, int hi)
{
hi++;
int res = 0;
if (lo != 0) {
while (lo + (lo & -lo) <= hi) {
lo += lo & -lo;
res = max(res, t0[lo]);
}
}
while (hi != lo) {
res = max(res, t1[hi]);
hi &= hi-1;
}
return res;
}
void update(int idx, int val)
{
int lo = idx;
int hi = idx+1;
while (hi <= n) {
if ((lo & -lo) > (hi & -hi) || lo == 0) {
if (t1[hi] == val) {
break;
}
t1[hi] = val;
val = max(t0[hi], t1[hi]);
}
else {
if (t0[lo] == val) {
break;
}
t0[lo] = val;
val = max(t0[lo], t1[lo]);
}
}
}
};
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);
}
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(0, 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 (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;
}