#include <bits/stdc++.h>
#define nozerous(x) (x & -x)
#define MOD 9901
#define EPS 0.00001
using namespace std;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int INF = (1 << 30), NMAX(100005), VMAX(1000000);
using VI = vector<int>;
using VVI = vector<VI>;
using VB = vector<bool>;
using Point = array<int, 2>;
using ll = long long;
using cd = complex<double>;
const double PI = acos(-1);
void BUNA(const string& task = "")
{
if (!task.empty())
freopen((task + ".in").c_str(), "r", stdin),
freopen((task + ".out").c_str(), "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
void PA()
{
exit(0);
}
vector<int> G[NMAX];
int val[NMAX], lev[NMAX], sz[NMAX], dad[NMAX], chain[NMAX], heavy_child[NMAX], label[NMAX], sizeCh[NMAX], chainparent[NMAX];
int *Arb[NMAX];
inline void subarb(int nod){
sz[nod] = 1;
int maxx = -1;
for(auto it: G[nod])
if(!dad[it]){
dad[it] = nod;
lev[it] = lev[nod] + 1;
subarb(it);
sz[nod] += sz[it];
if(maxx == -1)
maxx = it;
else if(sz[it] > sz[maxx])
maxx = it;
}
heavy_child[nod] = maxx;
}
inline void compute_chains(int nod){
if(heavy_child[nod] != -1)
chain[heavy_child[nod]] = chain[nod];
for(auto it: G[nod])
if(it != dad[nod])
compute_chains(it);
}
inline void compute_labels(int nod){
for(auto it: G[nod])
if(it != dad[nod]){
if(chain[it] != chain[nod])
chainparent[chain[it]] = nod;
compute_labels(it);
}
label[nod] = ++sizeCh[chain[nod]];
}
inline void update(int nod, int st, int dr, int wh){
if(st == dr)
Arb[chain[wh]][nod] = val[wh];
else {
int mij = (st + dr) / 2;
if(label[wh] <= mij)
update(2 * nod, st, mij, wh);
else update(2 * nod + 1, mij + 1, dr, wh);
Arb[chain[wh]][nod] = max(Arb[chain[wh]][2 * nod], Arb[chain[wh]][2 * nod + 1]);
}
}
int query(int nod, int st, int dr, int a, int b, int wh){
if(a <= st && dr <= b)
return Arb[wh][nod];
else {
int mij = (st + dr) / 2;
int r1 = 0, r2 = 0;
if(a <= mij)
r1 = query(2 * nod, st, mij, a, b, wh);
if(b > mij)
r2 = query(2 * nod + 1, mij + 1, dr, a, b, wh);
return max(r1, r2);
}
}
inline int search(int x, int y){
int rez = 0;
while(1){
if(chain[x] == chain[y]){
rez = max(rez, query(1, 1, sizeCh[chain[x]], min(label[x], label[y]), max(label[y], label[x]), chain[x]));
break;
}
if(lev[chainparent[chain[x]]] < lev[chainparent[chain[y]]])
swap(x, y);
rez = max(rez, query(1, 1, sizeCh[chain[x]], label[x], sizeCh[chain[x]], chain[x]));
x = chainparent[chain[x]];
}
return rez;
}
int main()
{
BUNA("heavypath");
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; ++i){
cin >> val[i];
chain[i] = i;
}
for(int i = 1; i < n; ++i){
int x, y;
cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
lev[1] = 1;
dad[1] = -1;
subarb(1);
compute_chains(1);
compute_labels(1);
set<int> s;
for(int i = 1; i <= n; ++i)
s.insert(chain[i]);
for(auto it: s){
Arb[it] = new int[4 * sizeCh[it] + 5];
for(int i = 0; i <= 4 * sizeCh[it] + 2; ++i)
Arb[it][i] = 0;
}
for(int i = 1; i <= n; ++i)
update(1, 1, sizeCh[chain[i]], i);
for(int i = 1; i <= m; ++i){
int t, x, y;
cin >> t >> x >> y;
if(t == 0){
val[x] = y;
update(1, 1, sizeCh[chain[x]], x);
}
else
cout << search(x, y) << '\n';
}
PA();
}