#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int NMAX = 100005;
vector<int> g[NMAX], p[NMAX];
int color[NMAX], ncolors, father[NMAX], ind[NMAX];
int v[NMAX], h[NMAX], dad[NMAX];
bool visited[NMAX];
int dfs(int node, int level) {
h[node] = level;
int dim = 1, mx = 0, currcolor;
for(auto it : g[node]) {
if(!visited[it]) {
visited[it] = 1;
dad[it] = node;
int aux = dfs(it, level + 1);
dim += aux;
if(aux > mx) {
mx = aux;
currcolor = color[it];
}
}
}
if(dim == 1) {
ncolors ++;
color[node] = ncolors;
ind[node] = 1;
p[ncolors].push_back(node);
father[ncolors] = node;
} else {
color[node] = currcolor;
ind[node] = p[currcolor].size() + 1;
p[currcolor].push_back(node);
father[currcolor] = node;
}
return dim;
}
vector<int> aint[NMAX];
void build(int c, int node, int le, int ri) {
if(le == ri) {
aint[c][node] = v[p[c][le - 1]];
return;
}
int mid = (le + ri) / 2;
build(c, node * 2, le, mid);
build(c, node * 2 + 1, mid + 1, ri);
aint[c][node] = max(aint[c][node * 2], aint[c][node * 2 + 1]);
}
void update(int c, int val, int pos, int node, int le, int ri) {
if(le == ri) {
aint[c][node] = val;
return;
}
int mid = (le + ri) / 2;
if(pos <= mid)
update(c, val, pos, node * 2, le, mid);
else
update(c, val, pos, node * 2 + 1, mid + 1, ri);
aint[c][node] = max(aint[c][node * 2], aint[c][node * 2 + 1]);
}
int query(int c, int from, int to, int node, int le, int ri) {
if(from <= le && ri <= to)
return aint[c][node];
int mid = (le + ri) / 2;
int ans = 0;
if(from <= mid)
ans = query(c, from, to, node * 2, le, mid);
if(mid < to)
ans = max(ans, query(c, from, to, node * 2 + 1, mid + 1, ri));
return ans;
}
int main() {
int n, m;
in >> n >> m;
for(int i = 1; i <= n; i ++)
in >> v[i];
for(int i = 1; i < n; i ++) {
int x, y;
in >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
visited[1] = 1;
dfs(1, 1);
for(int i = 1; i <= ncolors; i ++) {
aint[i].resize(4 * (p[i].size()) + 1);
build(i, 1, 1, p[i].size());
}
for(int qry = 1; qry <= m; qry ++) {
int t, x, y;
in >> t >> x >> y;
if(t == 0)
update(color[x], y, ind[x], 1, 1, p[color[x]].size());
if(t == 1) {
int ans = 0;
while(color[x] != color[y]) {
if(h[father[color[x]]] > h[father[color[y]]]) {
ans = max(ans, query(color[x], ind[x], ind[father[color[x]]], 1, 1, p[color[x]].size()));
x = dad[father[color[x]]];
} else {
ans = max(ans, query(color[y], ind[y], ind[father[color[y]]], 1, 1, p[color[y]].size()));
y = dad[father[color[y]]];
}
}
if(h[x] < h[y])
swap(x, y);
ans = max(ans, query(color[x], ind[x], ind[y], 1, 1, p[color[x]].size()));
out << ans << "\n";
}
}
return 0;
}