#include<bits/stdc++.h>
using namespace std;
// Khai báo kích thước mảng tối đa theo đề bài (N <= 2e5)
const int mx = 2e5 + 5;
int n;
int c[mx]; // Mảng lưu màu của từng đỉnh
int ans[mx]; // Mảng lưu kết quả (số màu khác nhau trong cây con)
vector<int> adj[mx]; // Danh sách kề để lưu cấu trúc cây
set<int> st[mx]; // Mỗi đỉnh có 1 cái set riêng để lưu các màu trong cây con của nó
// Hàm DFS duyệt từ dưới lên (Bottom-up)
void dfs(int u, int p) {
// 1. Khởi tạo: Mỗi đỉnh ban đầu chứa màu của chính nó
st[u].insert(c[u]);
// 2. Duyệt qua tất cả các con của u
for (int v : adj[u]) {
if (v != p) { // Tránh quay ngược lại cha
dfs(v, u); // Đệ quy xuống xử lý con trước
// 3. Kỹ thuật Small-to-Large (Gộp nhỏ vào lớn)
// So sánh kích thước set của cha (u) và con (v)
// Nếu set của con to hơn set của cha -> Đổi chỗ ngay lập tức
if (st[u].size() < st[v].size()) {
swap(st[u], st[v]); // O(1): Chỉ tráo đổi con trỏ, cực nhanh
}
// 4. Thực hiện gộp
// Lúc này đảm bảo st[v] luôn là set nhỏ hơn (hoặc bằng)
// Ta chỉ duyệt qua các phần tử của set nhỏ để bỏ vào set to
for (int color : st[v]) {
st[u].insert(color);
}
// Dọn dẹp set con để giải phóng bộ nhớ (không bắt buộc nhưng tốt)
st[v].clear();
}
}
// 5. Lưu kết quả
// Sau khi gộp hết tất cả con vào, kích thước set của u chính là số màu khác nhau
ans[u] = st[u].size();
}
int main() {
// Tối ưu tốc độ nhập xuất
cin.tie(0)->sync_with_stdio(0);
// Mở file nếu chạy trên máy (tiện cho debug)
if (fopen("Distinct_Colors.inp", "r")) {
freopen("Distinct_Colors.inp", "r", stdin);
freopen("Distinct_Colors.out", "w", stdout);
}
// Nhập số lượng đỉnh
cin >> n;
// Nhập màu cho từng đỉnh
for (int i = 1; i <= n; ++i) cin >> c[i];
// Nhập các cạnh và dựng cây
for (int i = 1; i < n; ++i) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
// Bắt đầu DFS từ gốc (đỉnh 1), cha của gốc là 0
dfs(1, 0);
// In kết quả cho từng đỉnh từ 1 đến n
for (int i = 1; i <= n; ++i) {
cout << ans[i] << " ";
}
return 0;
}