#include <bits/stdc++.h>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
const int LIM = 100'000;
int n, v[LIM + 5];
int q, t, x, y;
vector <int> edge[LIM + 5];
int subarbore[LIM + 5], parent[LIM + 5], level[LIM + 5];
inline void calc_subarbore(int crt, int prv){
parent[crt] = prv;
level[crt] = level[prv] + 1;
subarbore[crt] = 1;
for(auto nxt : edge[crt])
if(nxt != prv){
calc_subarbore(nxt, crt);
subarbore[crt] += subarbore[nxt];
}
}
int m, index_norm[LIM + 5];
int head_lant[LIM + 5], freq_lant[LIM + 5];
inline void create_lant(int crt, int prv, int hl){
head_lant [crt] = hl;
index_norm[crt] = ++m;
int maxv = 0, maxs = -1;
for(auto nxt : edge[crt])
if(nxt != prv){
if(subarbore[nxt] > maxv){
maxv = subarbore[nxt];
maxs = nxt;
}
}
if(maxs != -1){
create_lant(maxs, crt, hl);
for(auto nxt : edge[crt])
if(nxt != prv && nxt != maxs)
create_lant(nxt, crt, nxt);
}
}
struct SEGTREE{
int aint[4 * LIM + 5];
inline void update(int poz, int val, int nod=1, int st=1, int dr=n){
if(st == dr){
aint[nod] = val;
}else{
int md = ((st + dr) >> 1);
if(poz <= md) update(poz, val, 2*nod , st , md);
if(poz > md) update(poz, val, 2*nod+1, md+1, dr);
aint[nod] = max(aint[2*nod], aint[2*nod+1]);
}
}
inline int query(int qst, int qdr, int nod=1, int st=1, int dr=n){
if(st > dr)
return 0;
if(dr < qst || qdr < st)
return 0;
if(qst <= st && dr <= qdr){
return aint[nod];
}else{
int md = ((st + dr) >> 1), answer = 0;
answer = max(answer, query(qst, qdr, 2*nod , st , md));
answer = max(answer, query(qst, qdr, 2*nod+1, md+1, dr));
return answer;
}
}
} tree;
inline int query_lant(int nod1, int nod2){
int answer = 0;
while(head_lant[nod1] != head_lant[nod2]){
if(level[head_lant[nod1]] < level[head_lant[nod2]])
swap(nod1, nod2);
answer = max(answer, tree.query(index_norm[ head_lant[nod1] ], index_norm[ nod1 ]));
nod1 = parent[head_lant[nod1]];
}
if(index_norm[nod1] > index_norm[nod2])
swap(nod1, nod2);
answer = max(answer, tree.query(index_norm[nod1], index_norm[nod2]));
return answer;
}
int main (){
ios_base::sync_with_stdio(false);
fin.tie(nullptr), fout.tie(nullptr);
fin>>n>>q;
for(int i=1; i<=n; i++)
fin>>v[i];
for(int i=1; i < n; i++){
int u, v;
fin>>u>>v;
edge[u].push_back(v);
edge[v].push_back(u);
}
calc_subarbore(1, 0);
create_lant(1, 0, 1);
for(int i=1; i<=n; i++)
tree.update(index_norm[i], v[i]);
while(q--){
fin>>t>>x>>y;
if(t == 0){ ///update
tree.update(x, y);
}else{ ///query
fout<<query_lant(x, y)<<"\n";
}
}
return 0;
}