#include <bits/stdc++.h>
using namespace std;
 
#define int long long
#define dub long double
#define FOR(i, a, b) for (int (i)=(a); (i)<(b); ++(i))
#define ROF(i, a, b) for (int (i)=(a); (i)>(b); --(i))
#define CASET int _T; cin >> _T; FOR(caset, 1, _T+1)
#define pii pair<int,int>
#define t3i tuple<int,int,int>
#define mii map<int,int>
#define vi vector<int>
#define vb vector<bool>
#define vs vector<string>
#define vvi vector<vi>
#define vvb vector<vb>
#define vpii vector<pii>
#define vt3i vector<t3i>
#define vvpii vector<vpii>
#define sq(x) (x)*(x)
#define inv(x) powa(x, MOD-2)
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define SIZE(x) (signed)(x).size()
#define SUM(x) accumulate(ALL(x), 0LL)

long long INF = 1LL<<60;
long long MOD = 1e9 + 7;
 
namespace output {
    void pr(short x) { cout << x; }
    void pr(signed x) { cout << x; }
    void pr(long x) { cout << x; }
    void pr(long long x) { cout << x; }
    void pr(unsigned short x) { cout << x; }
    void pr(unsigned x) { cout << x; }
    void pr(unsigned long x) { cout << x; }
    void pr(unsigned long long x) { cout << x; }
    void pr(float x) { cout << x; }
    void pr(double x) { cout << x; }
    void pr(long double x) { cout << x; }
    void pr(char x) { cout << x; }
    void pr(const char* x) { cout << x; }
    void pr(const string& x) { cout << x; }
    void pr(bool x) { cout << x; }
    template<size_t sz> void pr(const bitset<sz>& x) { cout << x; }
    template<class T> void pr(const complex<T>& x) { cout << x; }
    
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T1, class T2, class T3> void pr(const tuple<T1,T2,T3>& x);
    template<class T> void pr(const T& x);
    
    template<class T, class... Ts> void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    template<class T1, class T2> void pr(const pair<T1,T2>& x) { pr("(",x.first,", ",x.second,")"); }
    template<class T1, class T2, class T3> void pr(const tuple<T1,T2,T3>& x) { pr("(",get<0>(x),", ",get<1>(x),", ",get<2>(x),")"); }
    template<class T> void pr(const T& x) { 
        pr("["); // const iterator needed for vector<bool>
        bool fst = 1; for (const auto& a: x) pr(!fst?", ":"",a), fst = 0; 
        pr("]");
    }
    
    void print() { pr("\n"); } // print w/ spaces
    template<class T, class... Ts> void print(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pr(" "); print(ts...); }
}
using namespace output;
 
template<typename T = int> vector<T> create(size_t n){ return vector<T>(n); }
template<typename T, typename... Args> auto create(size_t n, Args... args){ return vector<decltype(create<T>(args...))>(n, create<T>(args...)); }

template <class T1, class T2> istream &operator>>(istream &is, pair<T1,T2> &x) { is >> x.first >> x.second; return is; }
template <class T1, class T2, class T3> istream &operator>>(istream &is, tuple<T1,T2,T3> &x) { is >> get<0>(x) >> get<1>(x) >> get<2>(x); return is; }
template <class T> istream &operator>>(istream &is, vector<T> &v) { for (auto &x : v) is >> x; return is; }
int powa(int base, int exp) {
    int res = 1;
    while (exp) {
        if (exp&1) res = res*base % MOD;
        base = base*base % MOD;
        exp >>= 1;
    }
    return res;
}
bool mini(int &a, int b) { return b < a ? a = b, 1 : 0; }
bool maxi(int &a, int b) { return b > a ? a = b, 1 : 0; }

vvi nodes;
vi depth, par, subsz;
void szdfs(int u) {
	subsz[u] = 1;
	for (int &v : nodes[u]) if (v != par[u]) {
		depth[v] = 1 + depth[u];
		par[v] = u;
		szdfs(v);
		subsz[u] += subsz[v];
		if (subsz[v] > subsz[nodes[u][0]]) swap(v, nodes[u][0]);
	}
}

vi head, tin;
int t;
void dfs2(int u) {
	tin[u] = t++;
	for (int v : nodes[u]) if (v != par[u]) {
		head[v] = v == nodes[u][0] ? head[u] : v;
		dfs2(v);
	}
}

int n;
vi tree;
void segupd(int l, int r, int delta) {
	l += n;
	r += n;
	while (l <= r) {
		if (l&1) tree[l++] += delta;
		if (!(r&1)) tree[r--] += delta;
		l /= 2;
		r /= 2;
	}
}

int query(int x) {
	x = tin[x];
	x += n;
	int res = tree[x];
	x /= 2;
	while (x) {
		res += tree[x];
		x /= 2;
	}
	return res;
}

void upd(int a, int b, int delta) {
	int res = 0;
	while (head[a] != head[b]) {
		if (depth[head[a]] > depth[head[b]]) swap(a, b);
		segupd(tin[head[b]], tin[b], delta);
		b = par[head[b]];
	}
	if (depth[a] > depth[b]) swap(a, b);
	segupd(tin[a], tin[b], delta);
}

signed main() {
    ios::sync_with_stdio(0), cin.tie(0);
	
	cin >> n;
	vi col(n);
	cin >> col;


	nodes.resize(n);
	FOR(i, 0, n-1) {
		int x, y;
		cin >> x >> y;
		--x; --y;
		nodes[x].push_back(y);
		nodes[y].push_back(x);
	}
	
	depth.resize(n);
	par.resize(n);
	head.resize(n);
	tin.resize(n);
	subsz.resize(n);

	szdfs(0);
	dfs2(0);

	tree.resize(2*n);
	FOR(i, 0, n) tree[n+tin[i]] = subsz[i];
	
	vvpii colnodes(n+1);
	FOR(i, 0, n) colnodes[col[i]].emplace_back(depth[i], i);

	// print("subsz:", tin, subsz);

	FOR(c, 1, n+1) {
		// print("start:", tree);
		if (colnodes[c].empty()) {
			print(0);
			continue;
		}
		sort(RALL(colnodes[c]));
		int res = 0;
		vpii queries;
		for (pii pr : colnodes[c]) {
			int u = pr.second;
			int sumsz = 1;
			for (int v : nodes[u]) if (v != par[u]) {
				int sz = query(v);
				res += sz*(sz+1) / 2;
				sumsz += sz;
			}
			// print("thing", c, ":", u, sumsz);
			upd(u, 0, -sumsz);
			queries.emplace_back(u, sumsz);
		}
		int sz = query(0);
		res += sz*(sz+1) / 2;
		for (pii pr : queries) {
			upd(pr.first, 0, pr.second);
		}
		print(n*(n+1)/2 - res);
		// print("end:", tree);
	}
}

Measured memory_bytes: 50216