#include <bits/stdc++.h>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int nmax = 100005;
int n, m, value[nmax], cnt[nmax], z = 1, p[nmax], whatpos[nmax], whatlant[nmax], nv[nmax];
vector <int> G[nmax];
vector <pair <int, int> > G2[nmax];
vector <int> lant[nmax], aint[nmax];
void dfs(int nod, int tata, int nivel){
cnt[nod] = 1;
nv[nod] = nivel;
for (auto it : G[nod]){
if (it == tata){
continue;
}
dfs(it, nod, nivel + 1);
G2[nod].push_back({cnt[it], it});
cnt[nod] += cnt[it];
}
sort(G2[nod].begin(), G2[nod].end());
}
void dfs2(int nod){
whatlant[nod] = z;
lant[z].push_back(nod);
whatpos[nod] = lant[z].size();
for (int i = G2[nod].size() - 1; i >= 0; --i){
int vecin = G2[nod][i].second;
p[vecin] = nod;
dfs2(vecin);
if (i != 0){
++z;
}
}
}
void Build(int nod, int st, int dr, int l){
if (st == dr){
aint[l][nod] = value[lant[l][st - 1]];
return;
}
int mid = (st + dr) / 2;
Build(nod * 2, st, mid, l);
Build(nod * 2 + 1, mid + 1, dr, l);
aint[l][nod] = max(aint[l][nod * 2], aint[l][nod * 2 + 1]);
}
void Update(int nod, int st, int dr, int l, int pos){
if (st == dr){
aint[l][nod] = value[lant[l][st - 1]];
return;
}
int mid = (st + dr) / 2;
if (pos <= mid) Update(nod * 2, st, mid, l, pos);
else Update(nod * 2 + 1, mid + 1, dr, l, pos);
aint[l][nod] = max(aint[l][nod * 2], aint[l][nod * 2 + 1]);
}
int Query(int nod, int st, int dr, int l, int x, int y){
if (st >= x && dr <= y){
return aint[l][nod];
}
if (st > y || dr < x){
return 0;
}
int mid = (st + dr) / 2;
return max(Query(nod * 2, st, mid, l, x, y), Query(nod * 2 + 1, mid + 1, dr, l, x, y));
}
int QuerySupremFacutDePatrick(int x, int y){
int ans = 0;
while (x != y){
if (whatlant[x] == whatlant[y]){
if (whatpos[x] > whatpos[y]){
swap(x, y);
}
ans = max(ans, Query(1, 1, lant[whatlant[x]].size(), whatlant[x], whatpos[x], whatpos[y]));
y = x;
}
else{
int firstX = lant[whatlant[x]][0], firstY = lant[whatlant[y]][0];
if (nv[firstX] > nv[firstY]){
swap(x, y);
}
ans = max(ans, Query(1, 1, lant[whatlant[y]].size(), whatlant[y], 1, whatpos[y]));
y = p[lant[whatlant[y]][0]];
}
}
return ans;
}
int main(){
fin >> n >> m;
for (int i = 1; i <= n; ++i){
fin >> value[i];
}
for (int i = 1; i < n; ++i){
int x, y;
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, 0, 1);
dfs2(1);
for (int i = 1; i <= z; ++i){
aint[i].resize(4 * lant[i].size() + 4);
Build(1, 1, lant[i].size(), i);
}
while (m--){
int p, x, y;
fin >> p >> x >> y;
if (p == 0){
value[x] = y;
Update(1, 1, lant[whatlant[x]].size(), whatlant[x], whatpos[x]);
}
else{
fout << QuerySupremFacutDePatrick(x, y) << "\n";
}
}
fin.close();
fout.close();
return 0;
}