#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
const int NMAX = 100001;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, q;
int val[NMAX], level[NMAX], father[NMAX];
int tree[4 * NMAX];
int weight[NMAX];
int heavy_son[NMAX];
int head[NMAX];
int pos[NMAX];
int position;
vector<int> adj[NMAX];
void ReadGraph();
void Solve();
void Dfs(int x);
void Decompose(int x, int h);
int Query(int x, int y);
void UpdateTree(int node, int left, int right, int pos, int val);
int Query(int node, int left, int right, int a, int b);
int main()
{
ReadGraph();
Solve();
return 0;
}
void ReadGraph()
{
fin >> n >> q;
for (int i = 1; i <= n; ++i)
fin >> val[i];
int x, y;
for (int i = 1; i < n; ++i)
{
fin >> x >> y;
adj[x].push_back(y);
adj[y].push_back(x);
}
}
void Solve()
{
Dfs(1);
Decompose(1, 1);
for (int i = 1; i <= n; ++i)
UpdateTree(1, 1, n, pos[i], val[i]);
int op, x, y;
while (q--)
{
fin >> op >> x >> y;
if (op == 0)
UpdateTree(1, 1, n, pos[x], y);
else
fout << Query(x, y) << '\n';
}
}
void Dfs(int x)
{
int max_weight = 0;
weight[x] = 1;
for (int son : adj[x])
if (son != father[x])
{
father[son] = x;
level[son] = level[x] + 1;
Dfs(son);
weight[x] += weight[son];
if (weight[son] > max_weight)
{
max_weight = weight[son];
heavy_son[x] = son;
}
}
}
void Decompose(int x, int hd)
{
pos[x] = ++position;
head[x] = hd;
if (heavy_son[x])
Decompose(heavy_son[x], hd);
for (int son : adj[x])
if (heavy_son[x] != son && son != father[x])
Decompose(son, son);
}
int Query(int x, int y)
{
int res = 0;
while (head[x] != head[y])
{
if (level[head[x]] < level[head[y]])
swap(x, y);
res = max(res, Query(1, 1, n, pos[head[x]], pos[x]));
x = father[head[x]];
}
if (level[x] > level[y])
swap(x, y);
return max(res, Query(1, 1, n, pos[x], pos[y]));
}
void UpdateTree(int node, int left, int right, int pos, int val)
{
if (left == right)
{
tree[node] = val;
return;
}
int mid = (left + right) >> 1;
if (pos <= mid)
UpdateTree(2 * node, left, mid, pos, val);
else
UpdateTree(2 * node + 1, mid + 1, right, pos, val);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int Query(int node, int left, int right, int a, int b)
{
if (a <= left && right <= b)
return tree[node];
int mid = (left + right) >> 1;
int max1 = 0, max2 = 0;
if (a <= mid)
max1 = Query(2 * node, left, mid, a, b);
if (b > mid)
max2 = Query(2 * node + 1, mid + 1, right, a, b);
return max(max1, max2);
}