#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>> children(n + 1);
vector<int> parent(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;
parent[b] = a;
children[a].push_back(b);
}
// danh sách các node theo giá trị bài
vector<vector<int>> byValue(m + 1);
for (int u = 1; u <= n; ++u) if (1 <= v[u] && v[u] <= m) byValue[v[u]].push_back(u);
vector<int> freq(m + 1, 0);
vector<char> inside(n + 1, 0);
auto add_node = [&](int u, long long &bad_edges, long long &dupCnt){
// thêm u vào cửa sổ
inside[u] = 1;
if (++freq[v[u]] == 2) ++dupCnt; // vừa xuất hiện trùng
// cạnh với parent
if (parent[u] != 0 && !inside[parent[u]]) ++bad_edges;
// cạnh với con
for (int c : children[u]) {
if (inside[c]) {
// trước đó cạnh c trong, u ngoài → bad; giờ thì hết bad
--bad_edges;
}
}
};
auto remove_node = [&](int u, long long &bad_edges, long long &dupCnt){
// bỏ u ra khỏi cửa sổ
// cạnh với parent
if (parent[u] != 0 && !inside[parent[u]]) --bad_edges;
// cạnh với con
for (int c : children[u]) {
if (inside[c]) {
// giờ trở thành c trong, u ngoài → bad
++bad_edges;
}
}
if (--freq[v[u]] == 1) --dupCnt; // vừa bỏ bớt trùng
inside[u] = 0;
};
long long ans = 0;
long long bad_edges = 0; // số cạnh có con trong, cha ngoài
long long dupCnt = 0; // số giá trị xuất hiện >= 2 lần
int L = 1;
// đảm bảo L luôn <= v[root]
auto ensure_root_left = [&](){
if (L > v[1]) {
// đẩy L lùi lại sẽ không thuận tiện trong hai con trỏ tăng dần,
// vì thế ta chỉ cho phép đếm khi L <= v[root] <= R (xử lý ở vòng while bên dưới).
return;
}
};
// hai con trỏ trên [L, R]
for (int R = 1; R <= m; ++R) {
// thêm tất cả node có v = R
for (int u : byValue[R]) add_node(u, bad_edges, dupCnt);
// dịch L cho đến khi thỏa 3 điều kiện:
// 1) không trùng,
// 2) không có cạnh xấu,
// 3) L <= v[root] <= R (root thuộc cửa sổ).
while (L <= R && (dupCnt > 0 || bad_edges > 0 || !(L <= v[1] && v[1] <= R))) {
for (int u : byValue[L]) if (inside[u]) remove_node(u, bad_edges, dupCnt);
++L;
}
if (L <= R && (dupCnt == 0 && bad_edges == 0 && (L <= v[1] && v[1] <= R))) {// Với R cố định, mọi L hiện tại tạo ra đúng một khoảng hợp lệ kết thúc ở R
// (theo cách ta đã đẩy L tới nhỏ nhất thỏa điều kiện).
ans += (L <= R);
}
}
cout << ans << '\n';
return 0;
}