#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int Mn = 1e5 + 6;
int n, m, cnt, sol;
int val[Mn], weight[Mn], parent[Mn], depth[Mn], path[Mn], pos[Mn], psize[Mn], proot[Mn];
vector< int > g[Mn], tree[Mn];
void dfs(int x)
{
weight[x] = 1;
for (auto node : g[x])
if (!weight[node])
{
parent[node] = x;
depth[node] = depth[x] + 1;
dfs(node);
weight[x] += weight[node];
}
}
void hld(int x,int id)
{
path[x] = id;
pos[x] = ++psize[id];
int mx = 0;
for (auto node : g[x])
if (node != parent[x] && weight[node] > weight[mx])
mx = node;
if (!mx)
return;
hld(mx, id);
for (auto node : g[x])
if (node != parent[x] && node != mx)
{
proot[++cnt] = x;
hld(node, cnt);
}
}
void update(int node, int l, int r, int value, int pos, vector< int > &st)
{
if (l == r)
{
st[node] = value;
return;
}
int m = (l + r) / 2;
if (pos <= m)
update(2 * node, l, m, value, pos, st);
else
update(2 * node + 1, m + 1, r, value, pos, st);
st[node] = max(st[2 * node], st[2 * node + 1]);
}
void query(int node, int l, int r, int fi, int la, vector< int > &st)
{
if (fi <= l && r <= la)
{
sol = max(sol, st[node]);
return;
}
int m = (l + r) / 2;
if (fi <= m)
query(2 * node, l, m, fi, la, st);
if (m < la)
query(2 * node + 1, m + 1, r, fi, la, st);
}
int main()
{
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &val[i]);
for (int i = 1; i < n; i++)
{
int a, b;
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1);
depth[1] = 1;
hld(1, ++cnt);
for (int i = 1; i <= cnt; i++)
tree[i].resize(4 * psize[i]);
for (int i = 1; i <= n; i++)
update(1, 1, psize[path[i]], val[i], pos[i], tree[path[i]]);
for (; m; m--)
{
int t, x, y;
scanf("%d %d %d", &t, &x, &y);
if (t == 0)
update(1, 1, psize[path[x]], y, pos[x], tree[path[x]]);
else
{
int ans = 0;
int nr = 0;
while (nr < 10 && path[x] != path[y])
{
nr++;
if (depth[proot[path[x]]] < depth[proot[path[y]]])
swap(x,y);
sol = 0;
query(1, 1, psize[path[x]], 1, pos[x], tree[path[x]]);
ans = max(ans, sol);
x = proot[path[x]];
}
if (pos[x] > pos[y])
swap(x,y);
sol = 0;
query(1, 1, psize[path[x]], pos[x], pos[y], tree[path[x]]);
ans = max(ans, sol);
printf("%d\n", ans);
}
}
return 0;
}