#include<bits/stdc++.h>
using namespace std;
#define ALL(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define INF 1000000000
#define mod 1000000007
using ll=long long;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}
// v-> [ls[v],rs[v])
struct EulerTour{
    int V,pos;
    vector<vector<int>> g;
    vector<int> l,r,et;
    EulerTour(int V):V(V),g(V),l(V),r(V){}
    //bidirectional
    void add_edge(int u,int v){
        g[u].push_back(v);
        g[v].push_back(u);
    }
    void dfs(int pre,int now){
        l[now]=pos++;et.push_back(now);
        for(auto to:g[now])if(to!=pre){
            dfs(now,to);
        }
        r[now]=pos;
    }
    void build(int root){
        pos=0;dfs(-1,root);
    }
    int operator[](const int &k)const {
        return et[k];
    }
};

template<typename Monoid, typename OperatorMonoid=Monoid>
struct LazySegmentTree{
    // Monoid: 要素  OperatorMonoid: 作用素
    // 各マージ関数
    using F=function<Monoid(Monoid,Monoid)>;
    using G=function<Monoid(Monoid,OperatorMonoid)>;
    using H=function<OperatorMonoid(OperatorMonoid,OperatorMonoid)>;
 
    int sz,height;
    vector<Monoid> data;
    vector<OperatorMonoid> lazy;
    const F f;
    const G g;
    const H h;
    // 単位元
    const Monoid M1;
    const OperatorMonoid OM0;
 
    LazySegmentTree(int n,const F f,const G g,const H h,const Monoid &M1,const OperatorMonoid OM0)
    : f(f),g(g),h(h),M1(M1),OM0(OM0) {
        sz=1;height=0;
        while(sz<n) sz<<=1,height++;
        data.assign(2*sz,M1);lazy.assign(2*sz,OM0);
    }
 
    void set(int k,const Monoid &x){
        data[k+sz]=x;
    }
 
    //セグ木のbuild
    void build(){
        for(int k=sz-1;k>0;k--) data[k]=f(data[2*k+0],data[2*k+1]);
    }
 
    //伝播させる
    inline void propagate(int k){
        if(lazy[k]!=OM0){
            //子に伝えた後にkの場所のデータのほうの更新
            lazy[2*k+0]=h(lazy[2*k+0],lazy[k]);
            lazy[2*k+1]=h(lazy[2*k+1],lazy[k]);
            data[k]=reflect(k);
            lazy[k]=OM0;
        }
    }
 
    inline Monoid reflect(int k){
        return lazy[k]==OM0?data[k]:g(data[k],lazy[k]);
    }
    inline void recalc(int k){
        //下から上にdataの値を計算しなおす
        while(k>>=1)data[k]=f(reflect(2*k+0),reflect(2*k+1));
    }
    inline void thrust(int k){
        for(int i=height;i>0;i--) propagate(k>>i);
    }
 
    void update(int a,int b,const OperatorMonoid &x){
        thrust(a+=sz);
        thrust(b+=sz-1);
        for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
            if(l&1) lazy[l]=h(lazy[l],x),l++;
            if(r&1) --r,lazy[r]=h(lazy[r],x);
        }
        //recalcすればpが要らない
        recalc(a);
        recalc(b);
    }
 
    Monoid query(int a,int b){
        thrust(a+=sz);
        thrust(b+=sz-1);
        Monoid L=M1,R=M1;
        for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
            if(l&1) L=f(L,reflect(l++));
            if(r&1) R=f(reflect(--r),R);
        }
        return f(L,R);
    }
    
    Monoid operator[](const int &k){
        return query(k,k+1);
    }
 
    //ここから先もうしさんのライブラリにあったけど理解してないから
    //書くのはここまでにしておく
};

// 区間set 区間minmax
//この時h=g
// ll gen=-LINF;
// ll g(ll a,ll b){
//     if(b==gen) return a;
//     else return b;
// }

// 区間set 区間sum, fs:sum, sc:個数
ll gen=-LINF;
pair<ll,ll> f(pair<ll,ll> a,pair<ll,ll> b){
    return make_pair(a.first+b.first,a.second+b.second);
}
pair<ll,ll> g(pair<ll,ll> a,ll b){
    return make_pair(a.second*b,a.second);
}
ll h(ll a,ll b){
    return b==gen?a:b;
}


// 区間add区間minmax
// ll f(ll a,ll b){
//     return min(a,b);
// }
// ll g(ll a,ll b){
//     return a+b;
// }
// ll h(ll a,ll b){
//     return a+b;
// }


signed main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    
    int n;cin>>n;
    vector<int> c(n);
    rep(i,n){
        cin>>c[i];c[i]--;
    }
    EulerTour et(n);
    rep(i,n-1){
        int u,v;cin>>u>>v;u--,v--;
        et.add_edge(u,v);
    }
    et.build(0);

    vector<vector<int>> ord(n);// 色ごとのオイラーツアー逆順
    for(int i=n-1;i>=0;i--){
        ord[c[et.et[i]]].push_back(et.et[i]);
    }
    

    vector<ll> siz(n);
    vector<int> par(n,-1);
    function<ll(int,int)> dfssiz=[&](int pre,int now){
        ll ret=1;
        for(auto to:et.g[now])if(pre!=to){
            par[to]=now;
            ret+=dfssiz(now,to);
        }
        return siz[now]=ret;
    };
    dfssiz(-1,0);

    LazySegmentTree<pair<ll,ll>,ll> seg(n,f,g,h,make_pair(0,0),gen);
    rep(i,n) seg.set(i,make_pair(0,1));
    seg.build();

    vector<ll> ans(n,(ll)n*(n+1)/2);
    rep(i,n){
        seg.update(0,n,1);
        for(auto &j:ord[i]){
            for(auto &to:et.g[j])if(par[j]!=to){
                ll k=seg.query(et.l[to],et.r[to]).first;
                ans[i]-=k*(k+1)/2;
            }
            seg.update(et.l[j],et.r[j],0);
        }
        ll k=seg.query(0,n).first;
        ans[i]-=k*(k+1)/2;
    }

    rep(i,n) cout<<ans[i]<<endl;
    return 0;
}


Measured memory_bytes: 60872