#include <fstream>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
const int nmax = 100005;
vector<int> ls[nmax], comp_lant[nmax];
int nlant;
int a[nmax], x, y, i, j, t, n, m;
int niv[nmax], greu[nmax];
bool viz[nmax];
int dimlant[nmax], carelant[nmax];
int tatalant[nmax], nivlant[nmax];
int arb[nmax], pozlant[nmax];
void dfs(int x) {
int l = ls[x].size(), i, y, frunza = 1, k = -1;
viz[x] = 1;
greu[x] = 1;
for (i = 0; i < l; i++) {
y = ls[x][i];
if (viz[y]) continue;
frunza = 0;
niv[y] = niv[x]+1;
dfs(y);
greu[x] += greu[y];
if (k == -1) k = y;
else if (greu[y] > greu[k]) k = y;
}
if (frunza) {
nlant++;
dimlant[nlant]=1;
carelant[x] = nlant;
comp_lant[nlant].push_back(x);
return;
}
int k1 = k;
k = carelant[k];
dimlant[k]++;
carelant[x] = k;
comp_lant[k].push_back(x);
for (i = 0; i < l; i++) {
y = ls[x][i];
if (niv[y] < niv[x] || y == k1) continue;
k = carelant[y];
tatalant[ k ] = x;
nivlant[ k ] = niv[x];
}
}
void build(int cod, int st, int dr, int decalaj, int lant) {
if (st == dr) {
arb[cod+decalaj] = a[ comp_lant[lant][st-1] ];
return;
}
int mij = (st+dr)/2;
build(2*cod, st, mij, decalaj, lant);
build(2*cod+1, mij+1, dr, decalaj, lant);
arb[cod+decalaj] = max(arb[2*cod + decalaj], arb[2*cod+1 + decalaj]);
}
int gx, val;
void update(int cod, int st, int dr, int decalaj) {
if (st == dr) {
arb[cod+decalaj] = val;
return;
}
int mij = (st+dr)/2;
if (gx <= mij)
update(2*cod, st, mij, decalaj);
else update(2*cod+1, mij+1, dr, decalaj);
arb[cod+decalaj] = max(arb[2*cod + decalaj], arb[2*cod+1 + decalaj]);
}
int gl, gr;
int query(int cod, int st, int dr, int decalaj) {
if (gl <= st && dr <= gr)
return arb[cod+decalaj];
int mij = (st+dr)/2, max1 = 0;
if (gl <= mij)
max1 = query(2*cod, st, mij, decalaj);
if (mij < gr)
max1 = max(max1, query(2*cod+1, mij+1, dr, decalaj));
return max1;
}
void make_graph() {
niv[1]=1;
dfs(1);
for (i = 1; i <= nlant; i++) {
reverse(comp_lant[i].begin(), comp_lant[i].end());
if (i > 1)
pozlant[i] = pozlant[i-1] + 4 * dimlant[i-1];
build(1, 1, dimlant[i], pozlant[i], i);
}
}
void rezolva(int t, int x, int y) {
if (t == 0) {
int X = carelant[x];
gx = niv[x] - nivlant[X];
val = y;
update(1, 1, dimlant[X], pozlant[X]);
return;
}
int sol = 0;
while (1) {
if (carelant[x] == carelant[y]) {
if (niv[x] > niv[y])
swap(x, y);
int X = carelant[x], Y = carelant[y];
gl = niv[x] - nivlant[X];
gr = niv[y] - nivlant[X];
sol = max(sol, query(1, 1, dimlant[X], pozlant[X]) );
break;
}
if (nivlant[carelant[x]] < nivlant[carelant[y]])
swap(x, y);
int X = carelant[x], Y = carelant[y];
gl = 1;
gr = niv[x] - nivlant[X];
sol = max(sol, query(1, 1, dimlant[X], pozlant[X]) );
x = tatalant[X];
}
g << sol << '\n';
}
int main() {
f >> n >> m;
for (i = 1; i <= n; i++)
f >> a[i];
for (i = 1; i < n; i++) {
f >> x >> y;
ls[x].push_back(y);
ls[y].push_back(x);
}
make_graph();
for (i = 1; i <= m; i++) {
f >> t >> x >> y;
rezolva(t,x,y);
}
return 0;
}