#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int NMAX = 100005;
long long tree[4 * NMAX], st[NMAX], cost[NMAX], sz[NMAX], hindex[NMAX], heavyhead[NMAX], heavychild[NMAX], depth[NMAX], f[NMAX], parent[NMAX], cnt, n;
vector<vector<int>> v;
void build(int k, int l, int r)
{
if(l > r)
return;
if(l == r)
{
tree[k] = st[l];
return;
}
build(2*k, l, (l+r)/2);
build(2*k+1, (l+r)/2+1, r);
tree[k] = max(tree[2*k], tree[2*k+1]);
}
void update(int pos, int val, int k, int l, int r)
{
if(pos < l || pos > r || l > r)
return;
if(l == r && l == pos)
{
tree[k] = val;
return;
}
update(pos, val, 2*k, l, (l+r)/2);
update(pos, val, 2*k+1, (l+r)/2+1, r);
tree[k] = max(tree[2*k], tree[2*k+1]);
}
long long query(int i, int j, int k, int l, int r)
{
if(l > r)
return -1;
if(r < i || j < l)
return -1;
if(i <= l && r <= j)
return tree[k];
return max(query(i, j, 2*k, l, (l+r)/2), query(i, j, 2*k+1, (l+r)/2+1, r));
}
void dfs(int u)
{
heavychild[u] = 0;
sz[u] = cost[u];
for(auto it: v[u])
{
depth[it] = depth[u] + 1;
dfs(it);
sz[u] += sz[it];
if(sz[it] > sz[heavychild[u]])
heavychild[u] = it;
}
}
void dfsHeavyFirst(int u)
{
hindex[u] = ++cnt;
st[cnt] = cost[u];
if(heavychild[u] != 0)
{
heavyhead[heavychild[u]] = heavyhead[u];
dfsHeavyFirst(heavychild[u]);
}
for(auto it: v[u])
{
if(it != heavychild[u])
{
heavyhead[it] = it;
dfsHeavyFirst(it);
}
}
}
long long maxOnPath(int u, int v)
{
if(heavyhead[u] == heavyhead[v])
{
if(depth[u] < depth[v])
return query(hindex[u], hindex[v], 1, 1, n);
else
return query(hindex[v], hindex[u], 1, 1, n);
}
else if(depth[heavyhead[u]] < depth[heavyhead[v]])
return max(maxOnPath(u, parent[heavyhead[v]]), query(hindex[heavyhead[v]], hindex[v], 1, 1, n));
else
return max(maxOnPath(parent[heavyhead[u]], v), query(hindex[heavyhead[u]], hindex[u], 1, 1, n));
}
int main()
{
int q, i, a, b, root, op;
cin >> n >> q;
for(i = 1; i <= n; i++)
cin >> cost[i];
v.resize(n+1);
for(i = 1; i < n; i++)
{
cin >> a >> b;
parent[b] = a;
v[a].push_back(b);
f[b] = 1;
}
for(i = 1; i <= n; i++)
if(!f[i])
root = i;
depth[root] = 1;
dfs(root);
heavyhead[root] = root;
dfsHeavyFirst(root);
build(1, 1, n);
while(q--)
{
cin >> op >> a >> b;
if(op == 0)
update(hindex[a], b, 1, 1, n);
else
cout << maxOnPath(a, b) << '\n';
}
return 0;
}