#include <fstream>
#include <vector>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
int val[100100];
vector<vector<int> > gr(100100);
vector<bool> used(100100);
vector<vector<int> > arb(100100);
vector<vector<int> > Arb(100100);
vector<int> G (100100);
vector<int> tata_lant(100100);
vector<int> lant(100100);
vector<int> lv(100100);
vector<int> pos(100100);
int cont = 0;
void dfs(int root) {
G[root] = 1;
used[root] = true;
int MAX = 0;
int go = 0;
int last = 0;
for (auto &x : gr[root]) {
if (used[x]) {
last = x;
continue;
}
lv[x] = lv[root] + 1;
dfs(x);
G[root] += G[x];
if (MAX < G[x]) {
MAX = G[x];
go = x;
}
}
if (go == 0) {
cont++;
arb[cont].push_back(root);
lant[root] = cont;
pos[root] = 1;
} else {
arb[lant[go]].push_back(root);
lant[root] = lant[go];
pos[root] = arb[lant[root]].size();
for (auto &x : gr[root]) {
if (x == last || x == go) {
continue;
}
tata_lant[lant[x]] = root;
}
}
}
void Resize() {
for (int i = 1; i <= cont; i++) {
Arb[i].resize(arb[i].size() * 4);
}
}
void Update(int nod, int st, int dr, int poz, int val, int ARB) {
if (st == dr) {
Arb[ARB][nod] = val;
return;
}
int mij = st + dr;
mij /= 2;
if (mij >= poz) {
Update(nod * 2, st, mij, poz, val, ARB);
} else {
Update(nod * 2 + 1, mij + 1, dr, poz, val, ARB);
}
Arb[ARB][nod] = max(Arb[ARB][nod * 2], Arb[ARB][nod * 2 + 1]);
}
void Querry(int nod, int st, int dr, int MIN, int MAX, int ARB, int &maxx) {
if (MIN <= st && MAX >= dr) {
maxx = max(maxx, Arb[ARB][nod]);
return;
}
int mij = st + dr;
mij /= 2;
if (mij >= MIN) {
Querry(nod * 2, st, mij, MIN, MAX, ARB, maxx);
}
if (mij < MAX) {
Querry(nod * 2 + 1, mij + 1, dr, MIN, MAX, ARB, maxx);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> val[i];
}
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
gr[a].push_back(b);
gr[b].push_back(a);
}
dfs(1);
Resize();
for (int i = 1; i <= n; i++) {
Update(1, 1, arb[lant[i]].size(), pos[i], val[i], lant[i]);
}
for (int i = 1; i <= m; i++) {
int test, x, y;
cin >> test >> x >> y;
if (test == 0) {
val[x] = y;
Update(1, 1, arb[lant[x]].size(), pos[x], val[x], lant[x]);
} else {
int maxx = 0;
while (lant[x] != lant[y]) {
int lv_x = lv[arb[lant[x]][arb[lant[x]].size() - 1]];
int lv_y = lv[arb[lant[y]][arb[lant[y]].size() - 1]];
if (lv_x > lv_y) {
Querry(1, 1, arb[lant[x]].size(), pos[x], arb[lant[x]].size(), lant[x], maxx);
x = tata_lant[lant[x]];
} else {
Querry(1, 1, arb[lant[y]].size(), pos[y], arb[lant[y]].size(), lant[y], maxx);
y = tata_lant[lant[y]];
}
}
Querry(1, 1, arb[lant[x]].size(), min(pos[x], pos[y]), max(pos[x], pos[y]), lant[x], maxx);
cout << maxx << '\n';
}
}
return 0;
}