Distinct Colors
![]() |
All submissions for this problem are available.
You are given a tree with N vertices rooted at 1. You consider all the N subtrees (rooted at 1,2..N such that subtree rooted at i consists of i and all nodes which contain i as an ancestor).
Each node in the graph also consists of a color. The colors can be between 1 to K.
For each subtree find the no. of distinct colours in that subtree.
Output the sum of all these N numbers.
Each node in the graph also consists of a color. The colors can be between 1 to K.
For each subtree find the no. of distinct colours in that subtree.
Output the sum of all these N numbers.
Input
Next N-1 lines (from line 2 to line N) contain 1 integer each. (i + 1) th line contains the parent of i+2 and is guaranteed to be lesser than i+2. 1 is the root of the tree.
Next line contains N integers , each from 1 to K representing the colors of each node.
Output
Single integer corresponding to the required answer.
Constraints
Example
Input: 3 4 1 1 1 2 3 Output: 5
Explanation
The 3 subtrees are [1,2,3] , [2], [3] , which have 3,1,1 distinct colours respectively. So the answer is 5.
---------------------------------------------------------------EDITORIAL-----------------------------------------------------------------------------
A SUBTREE CONTAINS ALL ITS CHILDRENS SO WE CAN MAKE IT IN 1 D ARRAY , IF WE CREATE DFS TREE THAN WE CAN FIND ALL NODES WHICH COMES UNDER A NODE , NOW FOR EACH NODE A SET OF NODES FROM L TO R (ACCORDING TO ITS DFS TIME ) COMES AND WE HAVE TO COUNT NO OF DISTINCT COLOR FROM L TO R ,
SO FOR EACH NODE AS A ROOT NODE THERE EXISTS Li TO Ri NODES (ACCORDING TO DFS TREE )
SO WE NEED TO APPLY N QUERY OF FORM Li TO Ri AND IN EACH QUERY COUNT NO OF DISTINCT COLOR IN Li TO Ri , WHICH CAN BE DONE USING MO ALGORITHM .........
-------------------------------------------------------------------------CODE----------------------------------------------------------------------
#include<iostream>#include<bits/stdc++.h>
typedef long long int lli;
using namespace std;
bool visited[200010];
list<int> arr[200010];
int a[200010];
int sttime[200010];
int endtime[200010];
int tree[200010];
int vis=0;
int color[200010];
int bck_sz=447;
int has[1000000];
long long int fans=0;
long long int ans=0;
struct node{
int x;
int y;
// idx;
} brr[200010];
bool cmp(node a,node b)
{
long long i,j;
i=a.x/bck_sz;
j=b.x/bck_sz;
if(i==j)
{
if(a.y<b.y)
return 1;
else
return 0;
}
else{
if(i<j)
return 1;
else
return 0;
}
}
void add(int n)
{
if(has[n]==0)
{
has[n]++;
ans++;
}
else has[n]++;
}
void del(long long n)
{
if(has[n]==1) ans--;
if(has[n]>0)
{
has[n]--;
}
}
void dfs(int st)
{
list<int> ::iterator it;
tree[vis]=color[st];
sttime[st]=vis;
visited[st]=1;
for( it=arr[st].begin();it!=arr[st].end();it++)
{
if(visited[*it]==0)
{
vis++;
visited[*it]=1;
dfs(*it);
}
}
// cout<<"enfing "<<st<<" with "<<vis<<endl;
endtime[st]=vis;
}
int main()
{
int n,k;
cin>>n>>k;
for(int i=2;i<=n;i++)
{
cin>>a[i];
arr[a[i]].push_back(i);
}
for(int i=1;i<=n;i++)
cin>>color[i];
dfs(1);
//for(int i=0;i<=vis;i++) cout<<tree[i]<<" ";
// cout<<endl;
// cout<<"ese"<<endl;
//for(int i=1;i<=n;i++) cout<<sttime[i]<<" "<<endtime[i]<<endl;;
//cout<<endl;
for(int i=1;i<=n;i++)
{
brr[i-1].x= sttime[i];
brr[i-1].y=endtime[i];
}
sort(brr,brr+n,cmp);
// cout<<"clrs "<<endl;
// for(int i=1;i<=n;i++) cout<<color[i]<<" ";
long long int l=0,r=-1;
for(int i=0;i<n;i++)
{
int x=brr[i].x;
int y=brr[i].y;
// x++;
// y++;
// cout<<"range "<<x<<" "<<y<<endl;
// cout<<x<<" query "<<y<<endl;
while(r<y)
{
r++;
// cout<<"r "<<r<<endl;
// cout<<"adding"
add(tree[r]);
}
while(l>x)
{
l--;
add(tree[l]);
}
while(l<x)
{
del(tree[l]);
l++;
}
while(r>y)
{
del(tree[r]);
r--;
}
//cout<<"ans of this range "<<ans<<endl;
fans+=ans;
}
cout<<fans<<endl;
}
-------------------------------------------------------------this problrm can also solve by using set on each node and merge nodes from child to calculate for each node but for ac in given time we need to do a simple observation maximum no of copy is used for a linear tree which is very high soo for all node for its first child just replase it with its parent and for rest child copy so in case of linear tree no of copy used =0;
----------------------------------------code---------------------------------------------------------------------------------------------------------
- #include "bits/stdc++.h"
- using namespace std;
- const int N = 1e5 + 5;
- int n , k;
- vector < int > v[N];
- int col[N];
- int ans[N];
- set < int > s[N];
- int baap;
- long long sum = 0;
- void dfs(int node){
- int idx = -1;
- for(int x : v[node]){
- dfs(x);
- if(idx == -1 || s[x].size() > s[idx].size()){
- idx = x;
- }
- }
- if(idx != -1){
- s[node].swap(s[idx]);
- }
- s[node].insert(col[node]);
- for(int x : v[node]){
- if(x != idx){
- s[node].insert(s[x].begin() , s[x].end());
- }
- }
- sum += s[node].size();
- }
- int main(){
- for(int i = 2 ; i <= n ; ++i){
- v[baap].emplace_back(i);
- }
- for(int i = 1 ; i <= n ; ++i){
- }
- dfs(1);
- }
