#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
const int Max = 100010;
vector <int> lant[Max];
vector <int> Aint[Max];
vector <int> graf[Max];
int lantdenod[Max], v[Max], nivel[Max], tata[Max], sub[Max], poz[Max], lanturi = 0;
void build_aint(int lantisor, int node, int st, int dr){
if(st == dr){
Aint[lantisor][node] = v[lant[lantisor][st]];
return;
}
int mij = st+dr>>1;
build_aint(lantisor, node<<1, st, mij);
build_aint(lantisor, node<<1|1, mij+1, dr);
Aint[lantisor][node] = max(Aint[lantisor][node<<1], Aint[lantisor][node<<1|1]);
}
void update(int lantisor, int node, int st, int dr, int poz, int val){
if(st == dr){
Aint[lantisor][node] = val;
return;
}
int mij = st+dr>>1;
if(poz <= mij) update(lantisor, node<<1, st, mij, poz, val);
else update(lantisor, node<<1|1, mij+1, dr, poz, val);
Aint[lantisor][node] = max(Aint[lantisor][node<<1], Aint[lantisor][node<<1|1]);
}
void dfs(int node, int boss, int lvl){
nivel[node] = lvl;
sub[node] = 1;
for(int x : graf[node]){
if(x != boss){
tata[x] = node;
dfs(x, node, lvl+1);
sub[node] += sub[x];
}
}
if(graf[node].size() == 1 && node != 1){
++lanturi;
lant[lanturi].push_back(0);
lant[lanturi].push_back(node);
lantdenod[node] = lanturi;
poz[node] = 1;
return;
}
int best = 0;
for(int x : graf[node]){
if(x != boss && sub[x] > sub[best]){
best = x;
}
}
lantdenod[node] = lantdenod[best];
lant[lantdenod[best]].push_back(node);
poz[node] = lant[lantdenod[node]].size()-1;
}
int range_query(int lantisor, int node, int st, int dr, int a, int b){
if(st >= a && dr <= b){
return Aint[lantisor][node];
}
int mij = st+dr>>1, leftmax = -1, rightmax = -1;
if(a <= mij) leftmax = range_query(lantisor, node<<1, st, mij, a, b);
if(b > mij) rightmax = range_query(lantisor, node<<1|1, mij+1, dr, a, b);
return max(leftmax, rightmax);
}
int ans(int x, int y){
int best = -1;
while(true){
int lx = lantdenod[x];
int ly = lantdenod[y];
if(lx == ly){
int a = min(poz[x], poz[y]);
int b = max(poz[x], poz[y]);
best = max(best, range_query(lx, 1, 1, lant[lx].size()-1, a, b));
break;
}
if(nivel[lant[lx][1]] < nivel[lant[ly][1]])
swap(x, y);
lx = lantdenod[x];
ly = lantdenod[y];
best = max(best, range_query(lx, 1, 1, lant[lx].size()-1, 1, poz[x]));
x = tata[lant[lx][1]];
}
return best;
}
int main(){
int n, m;
f >> n >> m;
for(int i = 1; i <= n; ++i){
f >> v[i];
}
for(int i = 1, a, b; i < n; ++i){
f >> a >> b;
graf[a].push_back(b);
graf[b].push_back(a);
}
dfs(1, 0, 0);
for(int i = 1; i <= lanturi; ++i){
reverse(lant[i].begin()+1, lant[i].end());
Aint[i].resize(lant[i].size()<<2);
build_aint(i, 1, 1, lant[i].size()-1);
}
for(int i = 1; i <= n; ++i){
poz[i] = lant[lantdenod[i]].size()-poz[i];
}
for(int i = 1; i <= m; ++i){
int t, a, b;
f >> t >> a >> b;
if(t == 0){
update(lantdenod[a], 1, 1, lant[lantdenod[a]].size()-1, poz[a], b);
}
else g << ans(a, b) << '\n';
}
return 0;
}