macro_rules !read_value {($iter :expr ,($($t :tt ) ,*) ) =>{($(read_value !($iter ,$t ) ) ,*) } ;($iter :expr ,[$t :tt ;$len :expr ] ) =>{(0 ..$len ) .map (|_ |read_value !($iter ,$t ) ) .collect ::<Vec <_ >>() } ;($iter :expr ,{chars :$base :expr } ) =>{read_value !($iter ,String ) .chars () .map (|c |(c as u8 -$base as u8 ) as usize ) .collect ::<Vec <usize >>() } ;($iter :expr ,{char :$base :expr } ) =>{read_value !($iter ,{chars :$base } ) [0 ] } ;($iter :expr ,chars ) =>{read_value !($iter ,String ) .chars () .collect ::<Vec <char >>() } ;($iter :expr ,char ) =>{read_value !($iter ,chars ) [0 ] } ;($iter :expr ,usize1 ) =>{read_value !($iter ,usize ) -1 } ;($iter :expr ,$t :ty ) =>{$iter .next () .unwrap () .parse ::<$t >() .unwrap () } ;}
macro_rules !input_inner {($iter :expr ) =>{} ;($iter :expr ,) =>{} ;($iter :expr ,mut $var :ident :$t :tt $($r :tt ) *) =>{let mut $var =read_value !($iter ,$t ) ;input_inner !{$iter $($r ) *} } ;($iter :expr ,mut $var :ident $($r :tt ) *) =>{input_inner !{$iter ,mut $var :usize $($r ) *} } ;($iter :expr ,$var :ident :$t :tt $($r :tt ) *) =>{let $var =read_value !($iter ,$t ) ;input_inner !{$iter $($r ) *} } ;($iter :expr ,$var :ident $($r :tt ) *) =>{input_inner !{$iter ,$var :usize $($r ) *} } ;}
macro_rules !input {(source =$s :expr ,$($r :tt ) *) =>{let mut iter =$s .split_whitespace () ;input_inner !{iter ,$($r ) *} } ;(iter =$iter :ident ,$($r :tt ) *) =>{let s ={use std ::io ::Read ;let mut s =String ::new () ;std ::io ::stdin () .read_to_string (&mut s ) .unwrap () ;s } ;let mut $iter =s .split_whitespace () ;input_inner !{$iter ,$($r ) *} } ;($($r :tt ) *) =>{let s ={use std ::io ::Read ;let mut s =String ::new () ;std ::io ::stdin () .read_to_string (&mut s ) .unwrap () ;s } ;let mut iter =s .split_whitespace () ;input_inner !{iter ,$($r ) *} } ;}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Adjacent {
    pub to: usize,
    pub id: usize,
}
impl Adjacent {
    pub fn new(to: usize, id: usize) -> Adjacent {
        Adjacent { to: to, id: id }
    }
}
#[derive(Clone, Debug, Default)]
pub struct Graph {
    pub vsize: usize,
    pub esize: usize,
    pub graph: Vec<Vec<Adjacent>>,
}
impl Graph {
    pub fn new(vsize: usize) -> Graph {
        Graph {
            vsize: vsize,
            esize: 0,
            graph: vec![vec![]; vsize],
        }
    }
    pub fn add_edge(&mut self, from: usize, to: usize) {
        self.graph[from].push(Adjacent::new(to, self.esize));
        self.esize += 1;
    }
    pub fn add_undirected_edge(&mut self, u: usize, v: usize) {
        self.graph[u].push(Adjacent::new(v, self.esize));
        self.graph[v].push(Adjacent::new(u, self.esize));
        self.esize += 1;
    }
    pub fn vertices(&self) -> std::ops::Range<usize> {
        0..self.vsize
    }
    pub fn adjacency(&self, from: usize) -> &Vec<Adjacent> {
        &self.graph[from]
    }
}
#[derive(Default, Debug)]
pub struct TreeRec {
    n: usize,
    ans: Vec<usize>,
    c: Vec<usize>,
    vs: Vec<usize>,
}
impl TreeRec {
    pub fn new(n: usize, c: Vec<usize>) -> TreeRec {
        TreeRec {
            n: n,
            c: c,
            ans: vec![0; n],
            vs: vec![0; n],
        }
    }
    pub fn dfs(&mut self, u: usize, p: usize, graph: &Graph) -> HashMap<usize, usize> {
        let mut mp = HashMap::new();
        let c = self.c[u];
        for v in graph.adjacency(u) {
            if v.to != p {
                let mut m = self.dfs(v.to, u, graph);
                let x = self.vs[v.to];
                self.vs[u] += x;
                let sub = x - m.remove(&c).unwrap_or_default();
                self.ans[c] += sub * (sub.saturating_sub(1)) / 2;
                mp = merge(m, mp);
            }
        }
        self.vs[u] += 1;
        mp.insert(c, self.vs[u]);
        mp
    }
}
fn merge(m1: HashMap<usize, usize>, m2: HashMap<usize, usize>) -> HashMap<usize, usize> {
    let mut m1 = m1;
    let mut m2 = m2;
    if m1.len() < m2.len() {
        std::mem::swap(&mut m1, &mut m2);
    }
    for (k, v) in m2.into_iter() {
        *m1.entry(k).or_default() += v;
    }
    m1
}
use std::collections::HashMap;
fn main() {
    input! { n, c: [usize1; n], ab: [(usize1, usize1); n-1] };
    let mut g = Graph::new(n);
    let mut cnt = vec![0; n];
    for i in 0..n {
        cnt[c[i]] += 1;
    }
    let mut rec = TreeRec::new(n, c);
    for &(a, b) in &ab {
        g.add_undirected_edge(a, b);
    }
    let m = rec.dfs(0, n, &g);
    for i in 0..n {
        let x = n - m.get(&i).cloned().unwrap_or_default();
        println!(
            "{}",
            n * (n - 1) / 2 - rec.ans[i] - x * (x.saturating_sub(1)) / 2 + cnt[i]
        );
    }
}


Measured memory_bytes: 148052