#include <fstream>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
const int N_MAX = 100005;
int n, m, chain;
vector<int> graph[N_MAX];
int v[N_MAX], subCnt[N_MAX], h[N_MAX];
int chainIndex[N_MAX], chainStart[N_MAX], chainEnd[N_MAX];
int chainCount[N_MAX], chainParent[N_MAX], chainPos[N_MAX], chainNode[N_MAX];
int tree[4 * N_MAX];
void Dfs(int x, int p) {
h[x] = 1 + h[p];
subCnt[x] = 1;
for(auto y : graph[x]) {
if(y != p) {
Dfs(y, x);
subCnt[x] += subCnt[y];
}
}
int best = -1;
for(auto y : graph[x]) {
if(y != p) {
if(best == -1 || (best != -1 && subCnt[y] > subCnt[best]))
best = y;
}
}
for(auto y : graph[x]) {
if(y != p && y != best) {
chainParent[chainIndex[y]] = x;
}
}
if(best == -1)
chainIndex[x] = ++chain;
else
chainIndex[x] = chainIndex[best];
chainCount[chainIndex[x]]++;
}
void DetermineChains() {
Dfs(1, 0);
for(int i = 1; i <= chain; i++) {
chainStart[i] = 1 + chainEnd[i - 1];
chainEnd[i] = chainStart[i] + chainCount[i] - 1;
}
for(int i = 1; i <= n; i++) {
chainPos[i] = h[i] - h[chainParent[chainIndex[i]]];
chainNode[chainStart[chainIndex[i]] + chainPos[i] - 1] = i;
}
}
void Build(int x = 1, int l = 1, int r = n) {
if(l > r) return;
if(l == r) {
tree[x] = v[chainNode[l]];
return;
}
int med = (l + r) >> 1;
Build(x << 1, l, med);
Build(x << 1 | 1, med + 1, r);
tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
}
void Update(int pos, int val, int x = 1, int l = 1, int r = n) {
if(r < pos || pos < l) return;
if(l == r) {
tree[x] = val;
return;
}
int med = (l + r) >> 1;
Update(pos, val, x << 1, l, med);
Update(pos, val, x << 1 | 1, med + 1, r);
tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
}
int Query(int ql, int qr, int x = 1, int l = 1, int r = n) {
if(r < ql || qr < l) return 0;
if(ql <= l && r <= qr) return tree[x];
int med = (l + r) >> 1;
return max(Query(ql, qr, x << 1, l, med), Query(ql, qr, x << 1 | 1, med + 1, r));
}
int HeavyQuery(int x, int y) {
int ret = 0;
while(chainIndex[x] != chainIndex[y]) {
int xPar = chainParent[chainIndex[x]];
int yPar = chainParent[chainIndex[y]];
if(h[xPar] > h[yPar]) {
ret = max(ret, Query(chainStart[chainIndex[x]], chainStart[chainIndex[x]] + chainPos[x] - 1));
x = xPar;
}
else {
ret = max(ret, Query(chainStart[chainIndex[y]], chainStart[chainIndex[y]] + chainPos[y] - 1));
y = yPar;
}
}
return max(ret, Query(chainStart[chainIndex[x]] + min(chainPos[x], chainPos[y]) - 1,
chainStart[chainIndex[x]] + max(chainPos[x], chainPos[y]) - 1));
}
int main() {
ifstream f("heavypath.in");
ofstream g("heavypath.out");
f >> n >> m;
for(int i = 1; i <= n; i++)
f >> v[i];
for(int i = 1; i < n; i++) {
int x, y;
f >> x >> y;
graph[x].push_back(y);
graph[y].push_back(x);
}
DetermineChains();
Build();
while(m--) {
int t, x, y;
f >> t >> x >> y;
if(t == 0)
Update(chainStart[chainIndex[x]] + chainPos[x] - 1, y);
else
g << HeavyQuery(x, y) << '\n';
}
return 0;
}