#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
const int BUFFSIZE = (1 << 17);
char buf[BUFFSIZE];
int buff;
FILE* fin;
void read_init(char *_fin) {
fin = fopen(_fin, "r");
buff = BUFFSIZE - 1;
}
char read_ch() {
buff++;
if (buff == BUFFSIZE) {
buff = 0;
fread(buf, 1, BUFFSIZE, fin);
}
return buf[buff];
}
int read_u32() {
int nr = 0;
char ch = read_ch();
while (!('0' <= ch && ch <= '9') && ch != '-')
ch = read_ch();
int sgn = 1;
if (ch == '-')
sgn = -1, ch = read_ch();
do {
nr = nr * 10 + ch - '0';
ch = read_ch();
} while ('0' <= ch && ch <= '9');
return sgn * nr;
}
int vl[MAXN + 5];
vector<int>G[MAXN + 5];
vector<int>lant[MAXN + 5];
int k;
int sz[MAXN + 5], h[MAXN + 5], cl[MAXN + 5], pos[MAXN + 5], up[MAXN + 5];
int join(int x, int y) {
return max(x, y);
}
struct SegTree {
int n;
int *a;
SegTree(int _n = 0) {
n = _n;
a = new int [4 * n + 5];
}
SegTree(int _n, vector<int>_a) {
n = _n;
a = new int [4 * n + 5];
for (int i = 0; i < n; ++i)
update(i + 1, vl[_a[i]]);
}
void update(int pos, int val) {
upd(1, 1, n, pos, val);
}
int query(int l, int r) {
return qry(1, 1, n, l, r);
}
void upd(int node, int l, int r, int pos, int val) {
if (l == r) {
a[node] = val;
return ;
}
int mid = (l + r) / 2;
if (pos <= mid)
upd(2 * node, l, mid, pos, val);
else
upd(2 * node + 1, mid + 1, r, pos, val);
a[node] = join(a[2 * node], a[2 * node + 1]);
}
int qry(int node, int l, int r, int x, int y) {
if (l > r || y < l || r < x)
return 0;
if (x <= l && r <= y)
return a[node];
int mid = (l + r) / 2;
return join(qry(2 * node, l, mid, x, y), qry(2 * node + 1, mid + 1, r, x, y));
}
};
vector<SegTree>ch;
void dfs(int node, int f) {
h[node] = h[f] + 1;
up[node] = f;
int w = 0;
sz[node] = 1;
for (auto it:G[node])
if (it != f) {
dfs(it, node);
sz[node] += sz[it];
if (sz[it] > sz[w])
w = it;
}
if (w == 0) {
w = k;
k++;
} else {
w = cl[w];
}
cl[node] = w;
lant[w].push_back(node);
}
void Update(int x, int y) {
ch[cl[x]].update(pos[x], y);
}
int Query(int x, int y) {
if (cl[x] == cl[y])
return ch[cl[x]].query(min(pos[x], pos[y]), max(pos[x], pos[y]));
if (h[lant[cl[x]][0]] < h[lant[cl[y]][0]])
swap(x, y);
return join(ch[cl[x]].query(1, pos[x]), Query(up[lant[cl[x]][0]], y));
}
int main() {
read_init("heavypath.in");
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int n, m;
n = read_u32();
m = read_u32();
for (int i = 1; i <= n; ++i)
vl[i] = read_u32();
for (int i = 1; i < n; ++i) {
int x, y;
x = read_u32();
y = read_u32();
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, 0);
for (int i = 0; i < k; ++i) {
reverse(lant[i].begin(), lant[i].end());
for (int j = 0; j < (int)(lant[i].size()); ++j)
pos[lant[i][j]] = j + 1;
SegTree aux((int)(lant[i].size()), lant[i]);
ch.push_back(aux);
}
for (int i = 1; i <= m; ++i) {
int t, x, y;
t = read_u32();
x = read_u32();
y = read_u32();
if (t == 0)
Update(x, y);
else
printf("%d\n", Query(x, y));
}
return 0;
}