#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<int> v(n + 1);
for (int i = 1; i <= n; ++i) cin >> v[i];
vector<vector<int>> child(n + 1);
vector<int> par(n + 1, 0);
for (int i = 1; i < n; ++i) {
int a, b; // a là quản lý trực tiếp của b
cin >> a >> b;
par[b] = a;
child[a].push_back(b);
}
// Euler tour: tin/tout
vector<int> tin(n + 1), tout(n + 1);
int timer = 0;
{
vector<pair<int,int>> st;
st.reserve(2*n);
st.emplace_back(1, 0);
while (!st.empty()) {
auto tmp= st.back(); st.pop_back();
int u=tmp.first, state=tmp.second;
if (state == 0) {
tin[u] = ++timer;
st.emplace_back(u, 1);
for (int c : child[u]) st.emplace_back(c, 0);
} else {
tout[u] = timer;
}
}
}
// Với mỗi giá trị t (1..m), lưu danh sách các tin của các nút có giá trị t
vector<vector<int>> occ(m + 1);
for (int u = 1; u <= n; ++u) {
if (1 <= v[u] && v[u] <= m) occ[v[u]].push_back(tin[u]);
}
for (int t = 1; t <= m; ++t) {
sort(occ[t].begin(), occ[t].end()); // phòng khi không theo Euler sẵn
}
// bestX[y] = max x sao cho tồn tại cây con có "khoảng trống" (x, y) (y - x >= 2)
vector<int> bestX(m + 1, 0);
// Hàm kiểm tra "trong cây con u có xuất hiện giá trị t?"
auto in_subtree = [&](int u, int t) -> bool {
const auto &vec = occ[t];
if (vec.empty()) return false;
auto it = lower_bound(vec.begin(), vec.end(), tin[u]);
return (it != vec.end() && *it <= tout[u]);
};
// Duyệt từng nút, quét t=1..m để lấy các cặp liên tiếp trong S_u
for (int u = 1; u <= n; ++u) {
int prev = -1;
for (int t = 1; t <= m; ++t) {
if (!in_subtree(u, t)) continue;
if (prev != -1) {
if (t - prev >= 2) {
// có "lỗ" giữa prev và t trong cây con u
bestX[t] = max(bestX[t], prev);
}
}
prev = t;
}
}
// badLeft[R] = max_{y<=R} bestX[y]
vector<int> badLeft(m + 1, 0);
for (int R = 1; R <= m; ++R) {
badLeft[R] = max(badLeft[R - 1], bestX[R]);
}
// lastMissing[R] = giá trị bị thiếu (không ai có) gần nhất ≤ R; nếu không thiếu -> giữ nguyên
vector<int> lastMissing(m + 1, 0);
for (int t = 1; t <= m; ++t) {
lastMissing[t] = lastMissing[t - 1];
if (occ[t].empty()) lastMissing[t] = t;
}
// Tính đáp án
long long ans = 0;
int rootVal = v[1];
if (rootVal >= 1 && rootVal <= m) {
for (int R = 1; R <= m; ++R) {
if (R < rootVal) continue; // phải chứa rootint lower = max(badLeft[R], lastMissing[R]);
int toupper = min(R, rootVal), tolower = max(badLeft[R], lastMissing[R]);
if (toupper > tolower) ans += (toupper - tolower);
}
} else {
// root có giá trị ngoài [1..m] thì không có đoạn nào
ans = 0;
}
cout << ans << "\n";
return 0;
}