#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int MAXN = 1e5 + 5;
const int INF = 1e9;
int n, m;
struct AINT
{
int v[MAXN * 4];
void update0(int i, int l, int r, int x, int val)
{
if(r < x || x < l)
return;
if(l == r)
{
v[i] = val;
return;
}
int mid = (l + r) / 2;
update0(i * 2, l, mid, x, val);
update0(i * 2 + 1, mid + 1, r, x, val);
v[i] = max(v[i * 2], v[i * 2 + 1]);
}
void update(int x, int val)
{
update0(1, 1, n, x, val);
}
int query0(int i, int l, int r, int ql, int qr)
{
if(r < ql || qr < l)
return 0;
if(ql <= l && r <= qr)
return v[i];
int mid = (l + r) / 2;
return max(query0(i * 2, l, mid, ql, qr), query0(i * 2 + 1, mid + 1, r, ql, qr));
}
int query(int l, int r)
{
return query0(1, 1, n, l, r);
}
};
struct HLD
{
int parent[MAXN];
int heavy[MAXN];
int nxt[MAXN];
int pos[MAXN]; // in aint
int sz[MAXN];
int val[MAXN];
int depth[MAXN];
bool visited[MAXN];
vector<int> adj[MAXN];
vector<int> cd[MAXN];
AINT aint;
int cc = 0;
void dfs(int u)
{
if(visited[u])
return;
visited[u] = true;
sz[u] = 1;
int v1 = 0;
for(int v : adj[u])
{
if(visited[v])
continue;
cd[u].push_back(v);
depth[v] = depth[u] + 1;
parent[v] = u;
dfs(v);
sz[u] += sz[v];
if(!v1 || sz[v] > sz[v1])
{
v1 = v;
}
}
nxt[u] = v1;
}
void dfs1(int u)
{
pos[u] = ++cc;
if(cd[u].size() == 0)
return;
for(int v : cd[u])
{
if(v == nxt[u])
{
heavy[v] = heavy[u];
continue;
}
heavy[v] = v;
}
dfs1(nxt[u]);
for(int v : cd[u])
{
if(v == nxt[u])
continue;
dfs1(v);
}
}
void init()
{
heavy[1] = 1;
dfs(1);
dfs1(1);
for(int i = 1; i <= n; i++)
{
aint.update(pos[i], val[i]);
}
}
void update(int x, int val)
{
aint.update(pos[x], val);
}
int query0(int u, int minpos)
{
int ans = 0;
while(u)
{
int l, r;
l = max(minpos, pos[heavy[u]]);
r = pos[u];
ans = max(ans, aint.query(l, r));
u = parent[heavy[u]];
if(pos[u] < minpos)
continue;
}
return ans;
}
int query(int u, int v)
{
int ans = 0;
while(heavy[u] != heavy[v])
{
if(depth[u] < depth[v])
swap(u, v);
ans = max(ans, aint.query(pos[heavy[u]], pos[u]));
u = parent[heavy[u]];
}
if(depth[u] > depth[v])
swap(u, v);
ans = max(ans, aint.query(pos[u], pos[v]));
return ans;
}
};
HLD hld;
int32_t main()
{
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
cin >> hld.val[i];
}
for(int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
hld.adj[u].push_back(v);
hld.adj[v].push_back(u);
}
hld.init();
while(m--)
{
int t, x, y;
cin >> t >> x >> y;
if(t == 0)
{
hld.update(x, y);
}
else
{
cout << hld.query(x, y) << '\n';
}
}
return 0;
}