#include <stdio.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <algorithm>
using std::vector;
using std::queue;
using std::swap;
using std::max;
const int MAX_N = 100000;
int N, M;
int v[1 + MAX_N];
int father[1 + MAX_N];
vector<int> sons[1 + MAX_N];
vector<int> g[1 + MAX_N];
int maxim[MAX_N];
const int Inf = 1000000000;
int t [1 << 18];
int poz, val, a, b, rez;
void inline query(int p, int st, int dr)
{
if (a <= st && dr <= b)
{
rez = t [p];
return;
}
int m = (st + dr) / 2, m1 = - Inf, m2 = - Inf;
if (a <= m)
{
query (2 * p, st, m);
m1 = rez;
}
if (m + 1 <= b)
{
query (2 * p + 1, m + 1, dr);
m2 = rez;
}
rez = max (m1, m2);
}
void inline update (int p, int st, int dr)
{
if (st == dr)
{
t [p] = val;
return;
}
int m = (st + dr) / 2;
if (poz <= m)
update (2 * p, st, m);
else
update (2 * p + 1, m + 1, dr);
t [p] = max (t [2 * p], t [2 * p + 1]);
}
struct Node;
struct Chain {
Node* top;
int size;
int offset;
Chain() {
this->top = NULL;
this->size = 0;
this->offset = 0;
}
void setValue(int index, int value) {
//maxim[this->offset + index] = value;
poz = this->offset + index;
val = value;
update(1, 0, N - 1);
}
int getMax(int a, int b) {
//int i;
//int answer = 0;
//for (i = a; i <= b; i++) {
// answer = max(answer, maxim[this->offset + i]);
//}
//return answer;
::a = this->offset + a;
::b = this->offset + b;
rez = 0;
query(1, 0, N - 1);
return rez;
}
};
struct Node {
int index;
Node *father;
int weight;
int depth;
int chainPosition;
Chain *chain;
};
Node nodes[1 + MAX_N];
int chainsCount = 0;
Chain chains[1 + MAX_N];
void dfs2(int node, int nodeFather = 0) {
for (int neighbour : g[node]) {
if (neighbour != nodeFather) {
father[neighbour] = node;
sons[node].push_back(neighbour);
dfs2(neighbour, node);
}
}
}
void dfs(int node) {
nodes[node].index = node;
nodes[node].weight = 1;
int maxWeightNode = 0;
for (int son : sons[node]) {
nodes[son].depth = nodes[node].depth + 1;
nodes[son].father = &nodes[node];
dfs(son);
nodes[node].weight += nodes[son].weight;
if (nodes[maxWeightNode].weight < nodes[son].weight) {
maxWeightNode = son;
}
}
if (maxWeightNode != 0) {
nodes[node].chain = nodes[maxWeightNode].chain;
nodes[node].chainPosition = nodes[maxWeightNode].chainPosition + 1;
} else {
nodes[node].chain = &chains[chainsCount++];
nodes[node].chainPosition = 0;
}
nodes[node].chain->size++;
nodes[node].chain->top = &nodes[node];
}
void print(int node, int offset = 0) {
int i;
for (i = 0; i < offset; i++) {
printf(" ");
}
printf("%d: %d %d %d\n",
nodes[node].index,
nodes[node].depth,
nodes[node].weight,
nodes[node].chain->top->index);
for (int son : sons[node]) {
print(son, offset + 1);
}
}
int lca(int a, int b) {
while (nodes[a].chain != nodes[b].chain) {
if (nodes[a].chain->top->depth < nodes[b].chain->top->depth) {
swap(a, b);
}
a = nodes[a].chain->top->father->index;
}
if (nodes[a].depth < nodes[b].depth) {
return a;
} else {
return b;
}
}
int getMax(int a, int b) {
int answer = 0;
while (nodes[a].chain != nodes[b].chain) {
if (nodes[a].chain->top->depth < nodes[b].chain->top->depth) {
swap(a, b);
}
answer = max(answer, nodes[a].chain->getMax(
nodes[a].chainPosition, nodes[a].chain->top->chainPosition));
a = nodes[a].chain->top->father->index;
}
if (nodes[b].depth < nodes[a].depth) {
answer = max(answer, nodes[a].chain->getMax(
nodes[a].chainPosition, nodes[b].chainPosition));
} else {
answer = max(answer, nodes[a].chain->getMax(
nodes[b].chainPosition, nodes[a].chainPosition));
}
return answer;
}
int main() {
int i;
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d %d", &N, &M);
for (i = 1; i <= N; i++) {
scanf("%d", &v[i]);
}
for (i = 2; i <= N; i++) {
int a, b;
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs2(1);
dfs(1);
int val = 0;
for (i = 0; i < chainsCount; i++) {
chains[i].offset = val;
val += chains[i].size;
}
for (i = 1; i <= N; i++) {
nodes[i].chain->setValue(nodes[i].chainPosition, v[i]);
}
//print(1);
//*
for (i = 1; i <= M; i++) {
int t, x, y;
scanf("%d %d %d", &t, &x, &y);
if (t == 0) {
nodes[x].chain->setValue(nodes[x].chainPosition, y);
} else { // t == 1
printf("%d\n", getMax(x, y));
}
}//*/
return 0;
}