//---------- begin union_find ----------
#[allow(dead_code)]
mod union_find {
    use std;
    pub struct UF {
        parent: Vec<usize>,
        size: Vec<usize>,
        stack: Vec<Option<(usize, usize)>>,
    }
    impl UF {
        pub fn new(n: usize) -> UF {
            let mut u = UF {
                parent: vec![0; n],
                size: vec![1; n],
                stack: vec![],
            };
            u.init();
            u
        }
        pub fn init(&mut self) {
            for (i, p) in self.parent.iter_mut().enumerate() {
                *p = i;
            }
            self.size.clear();
            self.size.resize(self.parent.len(), 1);
            self.stack.clear();
        }
        pub fn root(&mut self, mut x: usize) -> usize {
            while self.parent[x] != x {
                x = self.parent[x];
            }
            x
        }
        pub fn same(&mut self, x: usize, y: usize) -> bool {
            self.root(x) == self.root(y)
        }
        pub fn unite(&mut self, mut x: usize, mut y: usize) -> Option<(usize, usize)> {
            x = self.root(x);
            y = self.root(y);
            if x == y {
                self.stack.push(None);
                return None;
            }
            if self.size[x] < self.size[y] {
                std::mem::swap(&mut x, &mut y);
            }
            self.size[x] += self.size[y];
            self.parent[y] = x;
            self.stack.push(Some((x, y)));
            Some((x, y))
        }
        pub fn undo(&mut self) -> Option<(usize, usize)> {
            self.stack
                .pop()
                .expect("union find undo error: stack is empty")
                .map(|(x, y)| {
                    self.size[x] -= self.size[y];
                    self.parent[y] = y;
                    (x, y)
                })
        }
        pub fn get_size(&mut self, x: usize) -> usize {
            let r = self.root(x);
            self.size[r]
        }
    }
}
//---------- end union_find ----------

use proconio::*;
use proconio::marker::Usize1;

fn calc(mut cnt: usize, l: usize, r: usize, e: Vec<(usize, usize, usize, usize)>, u: &mut union_find::UF, ans: &mut [usize]) {
    let m = (l + r) / 2;
    let mut left = vec![];
    let mut right = vec![];
    let mut used = 0;
    for (x, y, a, b) in e {
        if x <= l && r <= y {
            let a = u.root(a);
            let b = u.root(b);
            cnt += u.get_size(a) * u.get_size(b);
            u.unite(a, b);
            used += 1;
            continue;
        }
        if x < m {
            left.push((x, y, a, b));
        }
        if m < y {
            right.push((x, y, a, b));
        }
    }
    if l + 1 == r {
        ans[l] -= cnt;
    } else {
        calc(cnt, l, m, left, u, ans);
        calc(cnt, m, r, right, u, ans);
    }
    for _ in 0..used {
        u.undo();
    }
}

#[fastout]
fn run() {
    input! {
        n: usize,
        c: [Usize1; n],
        e: [(Usize1, Usize1); n - 1],
    }
    let mut edge = vec![];
    for &(a, b) in e.iter() {
        let x = c[a];
        let y = c[b];
        let (x, y) = (std::cmp::min(x, y), std::cmp::max(x, y));
        if x > 0 {
            edge.push((0, x, a, b));
        }
        if x + 1 < y {
            edge.push((x + 1, y, a, b));
        }
        if y + 1 < n {
            edge.push((y + 1, n, a, b));
        }
    }
    let mut ans = vec![n * (n + 1) / 2; n];
    for c in c.iter(){
        ans[*c] += 1;
    }
    let mut u = union_find::UF::new(n);
    calc(n, 0, n, edge, &mut u, &mut ans);
    for a in ans {
        println!("{}", a);
    }
}

fn main() {
    run();
}


Measured memory_bytes: 194592