#include <bits/stdc++.h>
using namespace std;
const int NMAX = 100000;
int N, M;
vector<int> G[NMAX+1];
int parent[NMAX+1], depth[NMAX+1], heavy[NMAX+1], sz[NMAX+1];
int head[NMAX+1], pos[NMAX+1];
long long values[NMAX+1];
int curPos;
struct SegmentTree {
vector<long long> tree;
int n;
SegmentTree(int n) : n(n) {
tree.assign(4*n, 0);
}
void update(int node, int l, int r, int idx, long long val) {
if(l == r) {
tree[node] = val;
return;
}
int mid = (l+r)/2;
if(idx <= mid) update(node*2, l, mid, idx, val);
else update(node*2+1, mid+1, r, idx, val);
tree[node] = max(tree[node*2], tree[node*2+1]);
}
long long query(int node, int l, int r, int ql, int qr) {
if(qr < l || r < ql) return LLONG_MIN;
if(ql <= l && r <= qr) return tree[node];
int mid = (l+r)/2;
return max(query(node*2, l, mid, ql, qr),
query(node*2+1, mid+1, r, ql, qr));
}
};
SegmentTree *seg;
int dfs(int u) {
sz[u] = 1;
int maxSubtree = 0;
for(int v : G[u]) {
if(v == parent[u]) continue;
parent[v] = u;
depth[v] = depth[u] + 1;
int subtree = dfs(v);
sz[u] += subtree;
if(subtree > maxSubtree) {
maxSubtree = subtree;
heavy[u] = v;
}
}
return sz[u];
}
void decompose(int u, int h) {
head[u] = h;
pos[u] = ++curPos;
seg->update(1, 1, N, pos[u], values[u]);
if(heavy[u]) decompose(heavy[u], h);
for(int v : G[u]) {
if(v != parent[u] && v != heavy[u]) {
decompose(v, v);
}
}
}
long long queryPath(int u, int v) {
long long res = LLONG_MIN;
while(head[u] != head[v]) {
if(depth[head[u]] < depth[head[v]]) swap(u, v);
res = max(res, seg->query(1, 1, N, pos[head[u]], pos[u]));
u = parent[head[u]];
}
if(depth[u] > depth[v]) swap(u, v);
res = max(res, seg->query(1, 1, N, pos[u], pos[v]));
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> N >> M;
for(int i=1; i<=N; i++) cin >> values[i];
for(int i=0; i<N-1; i++) {
int a, b; cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
seg = new SegmentTree(N);
dfs(1);
decompose(1, 1);
while(M--) {
int t, x; long long y;
cin >> t >> x >> y;
if(t == 0) {
seg->update(1, 1, N, pos[x], y);
} else {
cout << queryPath(x, (int)y) << "\n";
}
}
return 0;
}