#include <bits/stdc++.h>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
const int N = 100005;
int n, q;
vector <int> L[N];
bool viz[N];
int value[N], path[N], pos[N], pathParent[N], level[N];
int dp[N], cntPaths, len[N], start[N];
int aint[4 * N];
int queryAns = 0;
void updateAint(int node, int st, int dr, int targetPos, int val)
{
if (st == dr)
{
aint[node] = val;
return;
}
int mij = (st + dr) / 2;
if (targetPos <= mij)
updateAint(2 * node, st, mij, targetPos, val);
else
updateAint(2 * node + 1, mij + 1, dr, targetPos, val);
aint[node] = max(aint[2 * node], aint[2 * node + 1]);
}
void queryAint(int node, int st, int dr, int lft, int rgt)
{
if (st >= lft && dr <= rgt)
queryAns = max(queryAns, aint[node]);
else
{
int mij = (st + dr) / 2;
if (lft <= mij)
queryAint(2 * node, st, mij, lft, rgt);
if (rgt >= mij + 1)
queryAint(2 * node + 1, mij + 1, dr, lft, rgt);
}
}
int Query(int x, int y)
{
int ans = 0;
bool ok = 0;
while (!ok)
{
if (level[pathParent[path[x]]] < level[pathParent[path[y]]])
swap(x, y);
if (path[x] == path[y])
{
int lft = min(start[path[x]] + pos[x] - 1, start[path[x]] + pos[y] - 1);
int rgt = max(start[path[x]] + pos[x] - 1, start[path[x]] + pos[y] - 1);
queryAint(1, 1, n, lft, rgt);
ans = max(ans, queryAns);
queryAns = 0;
ok = 1;
}
else
{
queryAint(1, 1, n, start[path[x]], start[path[x]] + pos[x] - 1);
ans = max(ans, queryAns);
x = pathParent[path[x]];
queryAns = 0;
}
}
return ans;
}
void DFS(int node, int task)
{
viz[node] = 1;
if (task == 1)
{
if (L[node].size() == 1 && node != 1)
path[node] = ++cntPaths;
for (int nextNode : L[node])
if (!viz[nextNode])
{
int maxim = 0;
level[nextNode] = level[node] + 1;
DFS(nextNode, task);
dp[node] += dp[nextNode];
if (maxim < path[nextNode])
{
maxim = path[nextNode];
path[node] = path[nextNode];
}
}
dp[node]++;
for (int nextNode : L[node])
{
if (path[node] != path[nextNode])
pathParent[path[nextNode]] = node;
}
}
else
{
pos[node] = ++len[path[node]];
for (int nextNode : L[node])
if (!viz[nextNode])
DFS(nextNode, task);
}
}
int main()
{
fin >> n >> q;
for (int i = 1; i <= n; i++)
fin >> value[i];
for (int i = 1; i < n; i++)
{
int a, b;
fin >> a >> b;
L[a].push_back(b);
L[b].push_back(a);
}
level[1] = 1;
DFS(1, 1);
for (int i = 1; i <= n; i++)
viz[i] = 0;
DFS(1, 2);
int nextStart = 1;
for (int node = 1; node <= n; node++)
{
if (!start[path[node]])
{
start[path[node]] = nextStart;
nextStart = start[path[node]] + len[path[node]];
}
updateAint(1, 1, n, start[path[node]] + pos[node] - 1, value[node]);
}
while(q--)
{
int op, x, y;
fin >> op >> x >> y;
if (op == 0)
updateAint(1, 1, n, start[path[x]] + pos[x] - 1, y);
else
fout << Query(x, y) << "\n";
}
return 0;
}