#include <iostream>
#include <vector>
#include <math.h>
#define pb push_back
using namespace std;
const int N = 1e5 + 5;
int n, q, timer, clr, lift[N][20], tin[N], tout[N], up[N], color[N], subsize[N], v[N], euler[N], aint[4*N];
vector<int> g[N];
void get_size(int nod, int p) {
subsize[nod] = 1;
for(auto nxt : g[nod])
if(nxt != p) {
get_size(nxt, nod);
subsize[nod] += subsize[nxt];
}
}
void dfs(int nod, int p) {
lift[nod][0] = p;
for(int i=1; i<=log2(n); i++)
lift[nod][i] = lift[lift[nod][i-1]][i-1];
euler[++timer] = nod;
tin[nod] = timer;
if(!up[color[nod]])
up[color[nod]] = nod;
int maxi = 0;
for(auto nxt : g[nod])
if(nxt != p)
if(subsize[nxt] > subsize[maxi])
maxi = nxt;
if(!maxi)
return;
color[maxi] = color[nod];
dfs(maxi, nod);
for(auto nxt : g[nod])
if(nxt != p && nxt != maxi) {
color[nxt] = ++clr;
dfs(nxt, nod);
}
tout[nod] = timer;
}
bool is_ancestor(int a, int b) {
return tin[a] <= tin[b] && tout[b] <= tout[a];
}
int getlca(int a, int b) {
if(is_ancestor(a, b))
return a;
if(is_ancestor(b, a))
return b;
for(int i=log2(n); i>=0; i--)
if(lift[a][i] && is_ancestor(lift[a][i], b))
a = lift[a][i];
return a;
}
void build(int nod, int st, int dr) {
if(st == dr)
aint[nod] = v[euler[st]];
else {
int mid = (st + dr) / 2;
build(2*nod, st, mid);
build(2*nod+1, mid+1, dr);
aint[nod] = max(aint[2*nod], aint[2*nod+1]);
}
}
void update(int nod, int st, int dr, int pos) {
if(st == dr)
aint[nod] = v[euler[st]];
else {
int mid = (st + dr) / 2;
if(pos <= mid)
update(2*nod, st, mid, pos);
else
update(2*nod+1, mid+1, dr, pos);
aint[nod] = max(aint[2*nod], aint[2*nod+1]);
}
}
int getmax(int nod, int st, int dr, int l, int r) {
if(l <= st && dr <= r)
return aint[nod];
else {
int s1 = -1, s2 = -1, mid = (st + dr) / 2;
if(l <= mid)
s1 = getmax(2*nod, st, mid, l, r);
if(mid < r)
s2 = getmax(2*nod+1, mid+1, dr, l, r);
return max(s1, s2);
}
}
int query(int nod, int lca) {
int ans = -1;
while(color[nod] != color[lca]) {
ans = max(ans, getmax(1, 1, n, tin[up[color[nod]]], tin[nod]));
nod = lift[up[color[nod]]][0];
}
ans = max(ans, getmax(1, 1, n, min(tin[nod], tin[lca]), max(tin[nod], tin[lca])));
return ans;
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
cin.tie(nullptr)->sync_with_stdio(0);
cin >> n >> q;
for(int i=1; i<=n; i++)
cin >> v[i];
for(int i=1; i<n; i++) {
int x, y;
cin >> x >> y;
g[x].pb(y);
g[y].pb(x);
}
get_size(1, 0);
color[1] = ++clr;
dfs(1, 0);
build(1, 1, n);
while(q--) {
int tip, x, y;
cin >> tip >> x >> y;
if(tip == 1) {
int lca = getlca(x, y);
cout << max(query(x, lca), query(y, lca)) << '\n';
}
else {
v[x] = y;
update(1, 1, n, tin[x]);
}
}
return 0;
}