#include <iostream>
#include <string>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <iomanip>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
#include <assert.h>
using namespace std;


#define REP(i, n) for(ll i = 0;i < n;i++)
#define REPR(i, n) for(ll i = n;i >= 0;i--)
#define FOR(i, m, n) for(ll i = m;i < n;i++)
#define FORR(i, m, n) for(ll i = m;i >= n;i--)
#define REPO(i, n) for(ll i = 1;i <= n;i++)
#define ll long long
#define INF (ll)1 << 60
#define MINF (-1 * INF)
#define ALL(n) n.begin(),n.end()
#define MOD 1000000007
#define P pair<ll, ll>

ll n;

struct LazySegTree { //参照は + sz - 1;
	ll sz;
	vector<ll> node, lazy;
	vector<bool> lazyFlag;
	LazySegTree(ll n) {
		sz = 1;
		while (sz < n) sz *= 2;
		node.resize(2 * sz - 1);//
		lazy.resize(2 * sz - 1);//
		lazyFlag.resize(2 * sz - 1);
	}
	void eval(ll k, ll l, ll r) {
		if (lazyFlag[k]) {
			node[k] = lazy[k];//
			if (r - l > 1) {
				lazy[2 * k + 1] = lazy[k] / 2;//
				lazy[2 * k + 2] = lazy[k] / 2;//
				lazyFlag[2 * k + 1] = lazyFlag[2 * k + 2] = true;
			}
			lazyFlag[k] = false;
			lazy[k] = 0;//
		}
		else {
			if (lazy[k] == 0)return;
			node[k] += lazy[k];//
			if (r - l > 1) {
				lazy[2 * k + 1] += lazy[k] / 2;//
				lazy[2 * k + 2] += lazy[k] / 2;//
			}
			lazy[k] = 0;//
		}
	}
	void update(ll a, ll b, ll x, ll k = 0, ll l = 0, ll r = -1) {
		if (r < 0) r = sz;
		eval(k, l, r);
		if (b <= l || r <= a) return;
		if (a <= l && r <= b) {
			lazy[k] = (r - l) * x;//
			eval(k, l, r);

		}
		else {
			update(a, b, x, 2 * k + 1, l, (l + r) / 2);
			update(a, b, x, 2 * k + 2, (l + r) / 2, r);
			node[k] = node[2 * k + 1] + node[2 * k + 2];//
		}
	}
	void update2(ll a, ll b, ll k = 0, ll l = 0, ll r = -1) {
		if (r < 0) r = sz;
		eval(k, l, r);
		if (b <= l || r <= a) return;
		if (a <= l && r <= b) {
			lazy[k] = 0;//	
			lazyFlag[k] = true;
			eval(k, l, r);

		}
		else {
			update2(a, b, 2 * k + 1, l, (l + r) / 2);
			update2(a, b, 2 * k + 2, (l + r) / 2, r);
			node[k] = node[2 * k + 1] + node[2 * k + 2];//
		}
	}
	void update(ll a, ll x) {
		update(a, a + 1, x);
	}
	ll query(ll a, ll b, ll k = 0, ll l = 0, ll r = -1) {
		if (r < 0) r = sz;
		eval(k, l, r);
		if (b <= l || r <= a) return 0;//
		if (a <= l && r <= b) return node[k];
		ll vl = query(a, b, 2 * k + 1, l, (l + r) / 2);
		ll vr = query(a, b, 2 * k + 2, (l + r) / 2, r);
		return vl + vr;//
	}
	void init() {
		REPR(i, sz - 2) node[i] = node[2 * i + 1] + node[2 * i + 2];//
	}
};
struct HLD {
	vector<ll> g[510000];
	vector<ll> sz, in, out, head, rev, par; //rev = in -> index
	HLD(ll n) : sz(n), in(n), out(n), head(n), rev(n), par(n) {};
	void dfs_sz(ll a, ll p) {
		par[a] = p;
		sz[a] = 1;
		if (g[a].size() && g[a][0] == p) swap(g[a][0], g[a].back());
		for (auto& to : g[a]) {
			if (to == p)continue;
			dfs_sz(to, a);
			sz[a] += sz[to];
			if (sz[g[a][0]] < sz[to])swap(g[a][0], to);
		}
	}
	void dfs_hld(ll a, ll p, ll& t) {
		in[a] = t++;
		rev[in[a]] = a;
		for (auto& to : g[a]) {
			if (to == p)continue;
			head[to] = (g[a][0] == to ? head[a] : to);
			dfs_hld(to, a, t);
		}
		out[a] = t;
	}
	void edgeset(ll a, ll b) {
		g[a].push_back(b);
		g[b].push_back(a);
	}
	void build() {
		dfs_sz(0, -1);
		ll t = 0;
		dfs_hld(0, -1, t);
	}
	ll la(ll a, ll x) {
		while (1) {
			ll h = head[a];
			if (in[a] - x >= in[h])return rev[in[a] - x];
			x -= in[a] - in[h] + 1;
			a = par[h];
		}
	}
	ll lca(ll a, ll b) {
		for (;; b = par[head[b]]) {
			if (in[a] > in[b])swap(a, b);
			if (head[a] == head[b])return a;
		}
	}
	template< typename Q, typename F >
	ll query(ll a, ll b, ll ti, const Q& q, const F& f, bool edge = false) {
		ll l = ti, r = ti;
		for (;; b = par[head[b]]) {
			if (in[a] > in[b])swap(a, b), swap(l, r);
			if (head[a] == head[b])break;
			l = f(q(in[head[b]], in[b] + 1), l);
		}
		return f(f(q(in[a] + edge, in[b] + 1), l), r);
	}
	template < typename Q >
	void addpath(ll a, ll b, const Q& q, bool edge = false) { //path
		for (;; b = par[head[b]]) {
			if (in[a] > in[b])swap(a, b);
			if (head[a] == head[b])break;
			q(in[head[b]], in[b] + 1);
		}
		return q(in[a] + edge, in[b] + 1);
	}
	template < typename Q >
	void addst(ll a, ll x, const Q& q) { //subtree
		q(in[a], out[a], x);
	}
};

ll dep[210000], col[2100000];
vector<ll> g[210000];
vector<P> c[210000];
LazySegTree seg(210000);


void dfs(ll a, ll p, ll b) {
	dep[a] = b;
	REP(i, g[a].size()) {
		ll v = g[a][i];
		if (v == p)continue;
		dfs(g[a][i], a, b + 1);
	}
}
int main() {
	cin >> n;
	HLD tree(n);
	REP(i, n) {
		cin >> col[i];
		col[i]--;
	}
	REP(i, n - 1) {
		ll a, b;
		cin >> a >> b;
		a--;
		b--;
		tree.edgeset(a, b);
		g[a].push_back(b);
		g[b].push_back(a);
	}
	dfs(0, -1, 0);
	tree.build();
	REP(i, n) {//col sort
		c[col[i]].push_back(P(-1 * dep[i], i));
	}
	REP(i, n) sort(ALL(c[i]));
	REP(i, n) { // query
		ll ans = n * (n + 1) / 2;
		REP(j, c[i].size()) {
			ll v = c[i][j].second;
			//cout << v << " " << i << endl;
			REP(k, tree.g[v].size()) {
				ll now = tree.g[v][k];

				if (now == tree.par[v] or col[now] == col[v])continue;
				ll sz = tree.sz[now] - seg.query(tree.in[now], tree.out[now]);
				//cout << tree.sz[now] << " " << seg.query(tree.in[now], tree.out[now]) << " " << sz << " " << now << " !!!" << endl;
				ans -= sz * (sz + 1) / 2;
			}
			seg.update2(tree.in[v], tree.out[v], 0);
			seg.update(tree.in[v], tree.in[v] + 1, tree.sz[v]);
			//cout << seg.query(0, 210000) << endl;
		}
		ll nk = n - seg.query(0, 210000);
		ans -= nk * (nk + 1) / 2;
		seg.update2(0, 210000, 0);
		cout << ans << endl;
	}

}


Measured memory_bytes: 79156