Link to this code:
https://cses.fi/paste/cdb7092742c2c314be200e/#include<bits/stdc++.h>
using namespace std;
#define sum(a,b,m) ((a%m)+(b%m))%m
#define diff(a,b,m) ((a%m)-(b%m)+m)%m
#define pro(a,b,m) ((a%m)*(b%m))%m
#define ll long long
#define nl "\n"
#define M 1000000007
class SegmentTree{
int n;
set<int> s;
vector<int> arr;
vector<set<int>> tree;
public:
SegmentTree(int n,vector<int> &arr){
s.clear();
this->n=n;
this->arr=arr;
tree.resize(4*n);
}
set<int> merge(set<int> a,set<int> b){
set<int> c=a;
for(auto &p:b){
c.insert(p);
}
return c;
}
void build(int start,int end,int ind){
if(start==end){
tree[ind].insert(arr[start]);
return;
}
int mid=(start+end)>>1;
build(start,mid,2*ind);
build(mid+1,end,2*ind+1);
tree[ind]=merge(tree[2*ind],tree[2*ind+1]);
}
set<int> query(int l,int r,int start,int end,int ind){
if(l<=start && r>=end){
return tree[ind];
}
else if(l>end || r<start){
return this->s;
}
int mid=(start+end)>>1;
return merge(query(l,r,start,mid,2*ind),query(l,r,mid+1,end,2*ind+1));
}
};
class Graph{
int n,timer;
vector<vector<int>> adj;
vector<int> color;
vector<int> intime,outtime;
vector<int> flat;
public:
Graph(int n,vector<int> color){
this->n=n;
this->color.resize(n);
this->color=color;
adj.clear();
flat.clear();
adj.resize(n+1);
intime.resize(n+1);
outtime.resize(n+1);
timer=0;
}
void add_edge(int u,int v){
adj[u].push_back(v);
adj[v].push_back(u);
}
void dfs(int src,int par){
intime[src]=timer;
timer++;
flat.push_back(color[src-1]);
for(auto &child:adj[src]){
if(child!=par){
dfs(child,src);
}
}
outtime[src]=timer;
timer++;
flat.push_back(color[src-1]);
}
void solve(){
dfs(1,-1);
SegmentTree sg=SegmentTree(2*n,flat);
sg.build(0,2*n-1,1);
for(int i=1;i<=n;i++){
cout<<sg.query(intime[i],outtime[i],0,2*n-1,1).size()<<" ";
}
cout<<nl;
}
};
void solve(){
int n;cin>>n;
vector<int> color(n);
for(auto &p:color){
cin>>p;
}
Graph g=Graph(n,color);
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
g.add_edge(u,v);
}
g.solve();
}
int main(){
int t=1;
while(t--){
solve();
}
}