CodeEff/ECCO huggingface dataset:
# Original solution
import sys
import itertools

sys.setrecursionlimit(3 * 10**5)


class Node:
  def __init__(self, tpl):
    self.id = tpl[0] + 1
    self.c = int(tpl[1])
    self.relations = []

  def add_relation(self, node):
    self.relations.append(node)

  def dfs(self, prev_id):
    result = {self.id}
    for node in self.relations:
      if node.id != prev_id:
        result |= node.dfs(self.id)

    return result


def prepare_nodes(n):
  node_dict = {
    node.id: node
    for node in map(Node, enumerate(input().split()))
  }

  for _ in range(n - 1):
    a, b = list(map(int, input().split()))
    node_dict[a].add_relation(node_dict[b])
    node_dict[b].add_relation(node_dict[a])

  return node_dict


def main():
  n = int(eval(input()))
  nodes = list(prepare_nodes(n).values())

  paths_dict = {k: set() for k in range(1, n + 1)}

  for node in nodes:
    id_sets = [relation.dfs(node.id) for relation in node.relations]

    paths = {(node.id, node.id)}
    for id_set in id_sets:
      paths |= {tuple(sorted((node.id, id))) for id in id_set}

    cmbs = itertools.combinations(list(range(len(id_sets))), 2)
    for i, j in cmbs:
      paths |= {
        tuple(sorted((a, b)))
        for a in id_sets[i]
        for b in id_sets[j]
      }

    paths_dict[node.c] |= paths


  for paths in list(paths_dict.values()):
    print((len(paths)))


main()


# Optimized solution
import sys
import itertools

sys.setrecursionlimit(3 * 10**5)


class Node:
  def __init__(self, color):
    self.color = int(color) - 1
    self.children = []

  def add_child(self, node):
    self.children.append(node)

  @staticmethod
  def prepare_nodes(n):
    nodes = tuple(map(Node, input().split()))
    for _ in range(n - 1):
      a, b = [int(x) - 1 for x in input().split()]
      nodes[a].add_child(nodes[b])
      nodes[b].add_child(nodes[a])

    return nodes


def main():
  n = int(eval(input()))
  nodes = Node.prepare_nodes(n)

  dp = [0 for _ in range(n)]
  ans_list = [n*(n + 1) // 2 for _ in range(n)]

  def update_ans(s, color):
    ans_list[color] -= (s + dp[color]) * (s + dp[color] + 1) // 2

  def dfs(s, node, parent):
    color = node.color
    pre_s = s + dp[color]
    for child in node.children:
      if child == parent: continue

      dp[color] = -s
      s = dfs(s, child, node)
      update_ans(s, color)

    s += 1
    dp[color] = pre_s - s

    return s

  s = dfs(0, nodes[0], Node(-1))

  for i in range(n):
    update_ans(s, i)
    print((ans_list[i]))


main()
# Original solution
from collections import Counter
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline

N = int(readline())
C = tuple(map(lambda x: int(x)-1, readline().split()))

temp = map(int,read().split())
temp = zip(temp,temp)

adj = [list() for _ in range(N)]
for a,b in temp:
    adj[a-1].append(b-1)
    adj[b-1].append(a-1)


parent = [None]*N
parent[0] = -1

stack = [0]
order = []
while stack:
    p = stack.pop()
    order.append(p)
    for c in adj[p]:
        if parent[c] is None:
            parent[c] = p
            stack.append(c)

dp = [Counter() for _ in range(N)] # color-wise counter
subtreesize = [0]*N
cnt = [N*(N+1)//2]*N

for c in reversed(order):
    p = parent[c]
    if p >= 0:
        dp[c][C[c]] = subtreesize[c]+1
        x = subtreesize[c]-dp[c][C[p]]+1
        cnt[C[p]] -= x*(x+1)//2
        subtreesize[p] += subtreesize[c]+1

        a,b = dp[p],dp[c]
        if len(a) > len(b):
            a += b
            dp[p] = a
        else:
            b += a
            dp[p] = b
        dp[c] = None

dp[0][C[0]] = subtreesize[0]+1
for c in range(N):
    x = subtreesize[0]-dp[0][c]+1
    cnt[c] -= x*(x+1)//2

print(*cnt, sep='\n')


# Optimized solution
from collections import defaultdict
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline

N = int(readline())
C = tuple(map(lambda x: int(x)-1, readline().split()))

temp = map(int,read().split())
temp = zip(temp,temp)

adj = [list() for _ in range(N)]
for a,b in temp:
    adj[a-1].append(b-1)
    adj[b-1].append(a-1)


parent = [None]*N
parent[0] = -1

stack = [0]
order = []
while stack:
    p = stack.pop()
    order.append(p)
    for c in adj[p]:
        if parent[c] is None:
            parent[c] = p
            stack.append(c)

def merge(a,b):
    if len(a) > len(b):
        a,b = b,a
    for k,v in a.items():
        b[k] += v
    return b

dp = [defaultdict(int) for _ in range(N)] # color-wise counter
subtreesize = [0]*N
cnt = [N*(N+1)//2]*N

for c in reversed(order):
    p = parent[c]
    if p >= 0:
        dp[c][C[c]] = subtreesize[c]+1
        x = subtreesize[c]-dp[c][C[p]]+1
        cnt[C[p]] -= x*(x+1)//2
        subtreesize[p] += subtreesize[c]+1

        dp[p] = merge(dp[c],dp[p])
        dp[c] = None

dp[0][C[0]] = subtreesize[0]+1
for c in range(N):
    x = subtreesize[0]-dp[0][c]+1
    cnt[c] -= x*(x+1)//2

print(*cnt, sep='\n')
# Original solution
import sys
from collections import Counter, defaultdict, deque

sys.setrecursionlimit(2 * 10 ** 5)

(N,) = [int(x) for x in input().split()]
colors = [int(x) for x in input().split()]
edges = [[int(x) for x in input().split()] for i in range(N - 1)]
graph = defaultdict(list)
for u, v in edges:
    graph[u].append(v)
    graph[v].append(u)
parent = {1: None}
children = defaultdict(list)


def rootTree(node):
    for nbr in graph[node]:
        if nbr not in parent:
            parent[nbr] = node
            children[node].append(nbr)
            rootTree(nbr)


rootTree(1)


# cut tree into components that don't have a certain color
# if curr node is color c, each child that isn't color c forms a c-less component.
# Number of c-less path is size * (size + 1) / 2

colorlessCount = defaultdict(int)
colorlessComps = {}
for c in range(1, N + 1):
    colorlessComps[c] = [[]]


def buildComps(node):
    # Grow every colorless comp except for current color
    currColor = colors[node - 1]
    for c in colorlessComps:
        if c != currColor:
            colorlessComps[c][-1].append(node)
    for child in children[node]:
        colorlessComps[currColor].append([])
        buildComps(child)
        temp = colorlessComps[currColor].pop()
        s = len(temp)
        # print('size of colorless', currColor, ' is size', s, 'containing', temp)
        colorlessCount[currColor] += s * (s + 1) // 2


buildComps(1)
# print(colorToComps)
for c in colorlessComps:
    assert len(colorlessComps[c]) == 1
    temp = colorlessComps[c][0]
    s = len(temp)
    # print('size of root colorless', c, ' is size', s, 'containing', temp)
    colorlessCount[c] += s * (s + 1) // 2
# print(colorlessCount)
maxPairs = N * (N + 1) // 2
for c in range(1, N + 1):
    print((maxPairs - colorlessCount[c]))


# Optimized solution
import sys
from collections import Counter, defaultdict, deque

sys.setrecursionlimit(2 * 10 ** 5)

(N,) = [int(x) for x in input().split()]
colors = [int(x) for x in input().split()]
edges = [[int(x) for x in input().split()] for i in range(N - 1)]
graph = defaultdict(list)
for u, v in edges:
    graph[u].append(v)
    graph[v].append(u)
parent = {1: None}
children = defaultdict(list)


def rootTree(node):
    for nbr in graph[node]:
        if nbr not in parent:
            parent[nbr] = node
            children[node].append(nbr)
            rootTree(nbr)


rootTree(1)


colorlessCount = defaultdict(int)
colorlessTime = defaultdict(int)
t = 0
for c in range(1, N + 1):
    colorlessTime[c] = 0


def buildComps(node):
    global t
    t += 1
    currColor = colors[node - 1]
    colorlessTime[currColor] += 1
    for child in children[node]:
        oldCount = t - colorlessTime[currColor]
        colorlessTime[currColor] = t
        buildComps(child)
        s = t - colorlessTime[currColor]
        colorlessTime[currColor] = t - oldCount
        colorlessCount[currColor] += s * (s + 1) // 2


buildComps(1)
# print(colorToComps)
for c in colorlessTime:
    s = t - colorlessTime[c]
    colorlessCount[c] += s * (s + 1) // 2
maxPairs = N * (N + 1) // 2
for c in range(1, N + 1):
    print((maxPairs - colorlessCount[c]))
# Original solution
import sys
input = lambda : sys.stdin.readline().rstrip()

# 小さすぎても怒られるので
from collections import defaultdict
n = int(eval(input()))
sys.setrecursionlimit(max(1000, 2*n))

cs = [0] + [int(c) for c in input().split()]
ns = defaultdict(set)
for _ in range(n-1):
    a,b = [int(c) for c in input().split()]
    ns[a].add(b)
    ns[b].add(a)

ans = [0] * (n+1) # kを通らないパスの総数
def dfs(u, prev, ans):
    # result : {k: (kを通ってuで終わるパスの数=kを通らないと到達できない頂点数)}, (u以下の部分木のサイズ)
    k = cs[u]
    if len(ns[u])==1 and prev in ns[u]:
        eend, ss = {k : 1}, 1
    else:
        ss = 1
        eend = defaultdict(int)
        for v in ns[u]:
            if v==prev:
                continue
            end, s = dfs(v, u, ans)
            ss += s
            tmp = s - end.get(k, 0)
            ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
            for kk,vv in list(end.items()):
                if kk!=k:
                    eend[kk] += end[kk]
        eend[k] = ss
#     print(eend, ss, ans)
    return eend, ss
    
end, s = dfs(1, -1, ans)
for k in range(1, n+1):
    if k==cs[0]:
        continue
    tmp = s - end.get(k, 0)
    ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    
total = int(n * (n+1) / 2)
for i in range(1, n+1):
    print((total - ans[i]))

# Optimized solution

import sys
# 小さすぎても怒られるので
from collections import defaultdict
n = int(eval(input()))
sys.setrecursionlimit(max(1000, 2*n))

cs = [0] + [int(c) for c in input().split()]
ns = defaultdict(set)
for _ in range(n-1):
    a,b = [int(c) for c in input().split()]
    ns[a].add(b)
    ns[b].add(a)

ans = [0] * (n+1) # kを通らないパスの総数
minus = [0] * (n+1) # uの部分木のうち
minus0 = defaultdict(int)
st = {k: [] for k in range(1, n+1)}
nextu = {}
def dfs(u, prev, ans):
    global minus, st, minus0
    k = cs[u]
    st[k].append(u)
    ss = 1
    for v in ns[u]:
        if v==prev:
            continue
        nextu[u] = v
        s = dfs(v, u, ans)
        ss += s
        tmp = s - minus[v]
        ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    st[k].pop()
    if st[k]:
        minus[nextu[st[k][-1]]] += ss
    else:
        minus0[k] += ss
#     print(ss)
    return ss

dfs(1, -1, ans)
for k in range(1, n+1):
    tmp = n - minus0[k]
    ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    
total = int(n * (n+1) / 2)
for i in range(1, n+1):
    print((total - ans[i]))
# Original solution

import sys
# 小さすぎても怒られるので
from collections import defaultdict
n = int(eval(input()))
sys.setrecursionlimit(max(1000, 2*n))

cs = [0] + [int(c) for c in input().split()]
ns = defaultdict(set)
for _ in range(n-1):
    a,b = [int(c) for c in input().split()]
    ns[a].add(b)
    ns[b].add(a)

ans = [0] * (n+1) # kを通らないパスの総数
minus = [0] * (n+1) # uの部分木のうち
minus0 = defaultdict(int)
st = {k: [] for k in range(1, n+1)}
nextu = {}
def dfs(u, prev, ans):
    global minus, st, minus0
    k = cs[u]
    st[k].append(u)
    ss = 1
    for v in ns[u]:
        if v==prev:
            continue
        nextu[u] = v
        s = dfs(v, u, ans)
        ss += s
        tmp = s - minus[v]
        ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    st[k].pop()
    if st[k]:
        minus[nextu[st[k][-1]]] += ss
    else:
        minus0[k] += ss
#     print(ss)
    return ss

dfs(1, -1, ans)
for k in range(1, n+1):
    tmp = n - minus0[k]
    ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    
total = int(n * (n+1) / 2)
for i in range(1, n+1):
    print((total - ans[i]))

# Optimized solution

import sys
input = lambda : sys.stdin.readline().rstrip()

# 小さすぎても怒られるので
from collections import defaultdict
n = int(eval(input()))
sys.setrecursionlimit(max(1000, 2*n))

cs = [0] + [int(c) for c in input().split()]
ns = defaultdict(set)
for _ in range(n-1):
    a,b = [int(c) for c in input().split()]
    ns[a].add(b)
    ns[b].add(a)

ans = [0] * (n+1) # kを通らないパスの総数
minus = [0] * (n+1) # uの部分木のうち
minus0 = defaultdict(int)
st = {k: [] for k in range(1, n+1)}
nextu = {}
def dfs(u, prev, ans):
    global minus, st, minus0
    k = cs[u]
    st[k].append(u)
    ss = 1
    for v in ns[u]:
        if v==prev:
            continue
        nextu[u] = v
        s = dfs(v, u, ans)
        ss += s
        tmp = s - minus[v]
        ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    st[k].pop()
    if st[k]:
        minus[nextu[st[k][-1]]] += ss
    else:
        minus0[k] += ss
#     print(ss)
    return ss

dfs(1, -1, ans)
for k in range(1, n+1):
    tmp = n - minus0[k]
    ans[k] += (int(tmp * (tmp - 1) / 2) + tmp)
    
total = int(n * (n+1) / 2)
for i in range(1, n+1):
    print((total - ans[i]))
# Original solution
N = int(eval(input()))
Cs = list(map(int, input().split()))
adj = [[] for _ in range(N)]
for _ in range(N - 1):
    a, b = list(map(int, input().split()))
    adj[a - 1].append(b - 1)
    adj[b - 1].append(a - 1)

degs = [0] * N
clusters = [[] for _ in range(N)]


def go(curr, fro):
    col = Cs[curr] - 1
    deg = 1
    clust = {}
    for n in adj[curr]:
        if n == fro:
            continue
        ch_deg, ch_clust = yield n, curr
        clusters[col].append(ch_deg - ch_clust.get(col, 0))
        if len(ch_clust) > len(clust):
            clust, ch_clust = ch_clust, clust
        for k, v in list(ch_clust.items()):
            clust[k] = clust.get(k, 0) + v
        deg += ch_deg
    clust[col] = deg
    return deg, clust


stack = [[None, None], [go(0, -1), None]]
while len(stack) > 1:
    gen, val = stack[-1]
    try:
        params = gen.send(val)
    except StopIteration as e:
        stack[-2][1] = e.value
        stack.pop()
    else:
        stack.append([go(*params), None])

_, root_clust = stack[0][1]
for i in range(N):
    clusters[i].append(N - root_clust.get(i, 0))


for clust in clusters:
    tot = (N * N + N) // 2
    for cnt in clust:
        tot -= (cnt * cnt + cnt) // 2
    print(tot)


# Optimized solution
N = int(eval(input()))
Cs = list(map(int, input().split()))
adj = [[] for _ in range(N)]
for _ in range(N - 1):
    a, b = list(map(int, input().split()))
    adj[a - 1].append(b - 1)
    adj[b - 1].append(a - 1)

degs = [0] * N
clusters = [[] for _ in range(N)]


def go(curr, fro):
    col = Cs[curr] - 1
    deg = 1
    clust = {}
    for n in adj[curr]:
        if n == fro:
            continue
        ch_deg, ch_clust = yield n, curr
        clusters[col].append(ch_deg - ch_clust.get(col, 0))
        if len(ch_clust) > len(clust):
            clust, ch_clust = ch_clust, clust
        for k, v in list(ch_clust.items()):
            clust[k] = clust.get(k, 0) + v
        deg += ch_deg
    clust[col] = deg
    return deg, clust


def tramp(gen_fn, *args):
    stack = [gen_fn(*args)]
    val = None
    while stack:
        gen = stack[-1]
        try:
            params = gen.send(val)
        except StopIteration as e:
            stack.pop()
            val = e.value
        else:
            stack.append(go(*params))
            val = None
    return val


_, root_clust = tramp(go, 0, -1)
for i in range(N):
    clusters[i].append(N - root_clust.get(i, 0))


for clust in clusters:
    tot = (N * N + N) // 2
    for cnt in clust:
        tot -= (cnt * cnt + cnt) // 2
    print(tot)
# Original solution
import sys
input = lambda: sys.stdin.readline().rstrip()
N = int(input())
C = [int(a) - 1 for a in input().split()]
X = [[] for i in range(N)]
for i in range(N-1):
    x, y = map(int, input().split())
    x, y = x-1, y-1
    X[x].append(y)
    X[y].append(x)

def EulerTour(n, X, i0):
    def f(k):
        return k * (k + 1) // 2
    USED = [0] * n
    USEDORG = [0] * n
    USEDTMP = [0] * n
    P = [-1] * n
    Q = [~i0, i0]
    ct = -1
    ET = []
    ET1 = [0] * n
    ET2 = [0] * n
    DE = [0] * n
    ANS = [0] * n
    de = -1
    while Q:
        i = Q.pop()
        if i < 0:
            ET2[~i] = ct
            de -= 1
            USED[C[~i]] += 1 + USEDTMP[~i]
            USEDTMP[~i] = 0
            if ~i:
                p = P[~i]
                pc = C[p]
                k = ET2[~i] - ET1[~i] + 1 - USED[pc] + USEDORG[~i]
                ANS[pc] += f(k)
                USEDTMP[p] += k
            continue
        if i >= 0:
            if i:
                USEDORG[i] = USED[C[P[i]]]
            ET.append(i)
            ct += 1
            if ET1[i] == 0: ET1[i] = ct
            de += 1
            DE[i] = de
        for a in X[i][::-1]:
            if a != P[i]:
                P[a] = i
                for k in range(len(X[a])):
                    if X[a][k] == i:
                        del X[a][k]
                        break
                Q.append(~a)
                Q.append(a)
    for i in range(n):
        ANS[i] = f(n) - f(n - USED[i]) - ANS[i]
    return ANS

ANS = EulerTour(N, X, 0)
print(*ANS, sep = "\n")


# Optimized solution
import sys
input = lambda: sys.stdin.readline().rstrip()
N = int(input())
C = [int(a) - 1 for a in input().split()]
X = [[] for i in range(N)]
for i in range(N-1):
    x, y = map(int, input().split())
    X[x-1].append(y-1)
    X[y-1].append(x-1)

def EulerTour(n, X, i0):
    f = lambda k: k * (k + 1) // 2
    USED = [0] * n
    ORG = [0] * n
    TMP = [0] * n
    P = [-1] * n
    Q = [~i0, i0]
    ct = -1
    ET1 = [0] * n
    ET2 = [0] * n
    ANS = [f(n)] * n
    while Q:
        i = Q.pop()
        if i < 0:
            i = ~i
            ET2[i] = ct
            USED[C[i]] += 1 + TMP[i]
            if i:
                p = P[i]
                k = ET2[i] - ET1[i] + 1 - USED[C[p]] + ORG[i]
                ANS[C[p]] -= f(k)
                TMP[p] += k
            continue
        if i >= 0:
            if i: ORG[i] = USED[C[P[i]]]
            ct += 1
            if ET1[i] == 0: ET1[i] = ct
        for a in X[i][::-1]:
            if a != P[i]:
                P[a] = i
                for k in range(len(X[a])):
                    if X[a][k] == i:
                        del X[a][k]
                        break
                Q.append(~a)
                Q.append(a)
    for i in range(n):
        ANS[i] -= f(n - USED[i])
    return ANS

print(*EulerTour(N, X, 0), sep = "\n")
# Original solution
import sys
input = lambda: sys.stdin.readline().rstrip()
N = int(input())
C = [int(a) - 1 for a in input().split()]
X = [[] for i in range(N)]
for i in range(N-1):
    x, y = map(int, input().split())
    X[x-1].append(y-1)
    X[y-1].append(x-1)

def EulerTour(n, X, i0):
    f = lambda k: k * (k + 1) // 2
    USED = [0] * n
    ORG = [0] * n
    TMP = [0] * n
    P = [-1] * n
    ct = -1
    ET1 = [0] * n
    ET2 = [0] * n
    ANS = [f(n)] * n
    IND = [0] * n
    i = i0
    while i >= 0:
        ind = IND[i]
        if ind == 0:
            if i: ORG[i] = USED[C[P[i]]]
            ct += 1
            ET1[i] = ct
        
        if ind >= len(X[i]):
            ET2[i] = ct
            USED[C[i]] += 1 + TMP[i]
            if i:
                k = ET2[i] - ET1[i] + 1 - USED[C[P[i]]] + ORG[i]
                ANS[C[P[i]]] -= f(k)
                TMP[P[i]] += k
            i = P[i]
            continue
        
        j = X[i][ind]
        if P[i] == j:
            IND[i] += 1
            continue
        P[j] = i
        IND[i] += 1
        i = j
    
    for i in range(n):
        ANS[i] -= f(n - USED[i])
    return ANS

print(*EulerTour(N, X, 0), sep = "\n")


# Optimized solution
import sys
input = lambda: sys.stdin.readline().rstrip()
N = int(input())
C = [int(a) - 1 for a in input().split()]
X = [[] for i in range(N)]
for i in range(N-1):
    x, y = map(int, input().split())
    X[x-1].append(y-1)
    X[y-1].append(x-1)

def EulerTour(n, X, i0):
    f = lambda k: k * (k + 1) // 2
    USED = [0] * n
    ORG = [0] * n
    TMP = [0] * n
    P = [-1] * n
    ct = -1
    ET1 = [0] * n
    ET2 = [0] * n
    ANS = [f(n)] * n
    IND = [len(x) for x in X]
    i = i0
    while i >= 0:
        ind = IND[i]
        if not ind:
            ET2[i] = ct
            USED[C[i]] += 1 + TMP[i]
            if i:
                k = ET2[i] - ET1[i] + 1 - USED[C[P[i]]] + ORG[i]
                ANS[C[P[i]]] -= f(k)
                TMP[P[i]] += k
            i = P[i]
            continue
        
        j = X[i][ind - 1]
        if P[i] == j:
            IND[i] -= 1
            continue
        
        P[j] = i
        IND[i] -= 1
        i = j
        ORG[i] = USED[C[P[i]]]
        ct += 1
        ET1[i] = ct
    
    for i in range(n):
        ANS[i] -= f(n - USED[i])
    return ANS

print(*EulerTour(N, X, 0), sep = "\n")
# Original solution
from typing import List
import sys

n = int(eval(input()))
c = list(map(int, input().split()))
c = [x-1 for x in c]
# print(c)
adj = [[] for i in range(n)]
for i in range(n-1):
    a, b = tuple(map(int, input().split()))
    a -= 1
    b -= 1
    adj[a].append(b)
    adj[b].append(a)


size: List[int] = [1 for i in range(n)]
stack: List[List[int]] = [[] for color in range(n)]
in_time: List[int] = [-1 for i in range(n)]
out_time: List[int] = [-1 for i in range(n)]
timer = 0
total = n*(n+1)//2
ans: List[int] = [total for color in range(n)]
# print(ans)


def dfs(parent: int, root: int):
    global timer
    in_time[root] = timer
    timer += 1

    for child in adj[root]:
        if parent == child:
            continue
        dfs(root, child)
        size[root] += size[child]

        cnt = size[child]
        while stack[c[root]]:
            x = stack[c[root]][-1]
            if in_time[x] > in_time[root] and out_time[x] != -1:
                cnt -= size[x]
                stack[c[root]].pop()
            else:
                break
        ans[c[root]] -= cnt*(cnt+1)//2

    out_time[root] = timer
    timer += 1

    stack[c[root]].append(root)


sys.setrecursionlimit(10**6)

dfs(0, 0)
# print(size)
for color in range(n):
    cnt = n
    while len(stack[color]) > 0:
        x = stack[color][-1]
        cnt -= size[x]
        stack[color].pop()
    # print("node:", -1, "color:", color, "cnt:", cnt)
    ans[color] -= cnt*(cnt+1)//2
    print((ans[color]))


# Optimized solution
from typing import List
import sys

input = lambda: sys.stdin.readline().rstrip()
n = int(eval(input()))
c = list(map(int, input().split()))
c = [x-1 for x in c]
# print(c)
adj = [[] for i in range(n)]
for i in range(n-1):
    a, b = tuple(map(int, input().split()))
    a -= 1
    b -= 1
    adj[a].append(b)
    adj[b].append(a)


size: List[int] = [1 for i in range(n)]
stack: List[List[int]] = [[] for color in range(n)]
in_time: List[int] = [-1 for i in range(n)]
out_time: List[int] = [-1 for i in range(n)]
timer = 0
total = n*(n+1)//2
ans: List[int] = [total for color in range(n)]
# print(ans)


def dfs(parent: int, root: int):
    global timer
    in_time[root] = timer
    timer += 1

    for child in adj[root]:
        if parent == child:
            continue
        dfs(root, child)
        size[root] += size[child]

        cnt = size[child]
        while stack[c[root]]:
            x = stack[c[root]][-1]
            if in_time[x] > in_time[root] and out_time[x] != -1:
                cnt -= size[x]
                stack[c[root]].pop()
            else:
                break
        ans[c[root]] -= cnt*(cnt+1)//2

    out_time[root] = timer
    timer += 1

    stack[c[root]].append(root)


sys.setrecursionlimit(10**6)

dfs(0, 0)
# print(size)
for color in range(n):
    cnt = n
    while len(stack[color]) > 0:
        x = stack[color][-1]
        cnt -= size[x]
        stack[color].pop()
    # print("node:", -1, "color:", color, "cnt:", cnt)
    ans[color] -= cnt*(cnt+1)//2
    print((ans[color]))