Submission #1148414

#TimeUsernameProblemLanguageResultExecution timeMemory
1148414Faisal_SaqibTeam Coding (EGOI24_teamcoding)C++20
81 / 100
4094 ms42380 KiB
#include <bits/stdc++.h>

using namespace std;

const int N=1e5+10;
vector<int> ma[N];
int h[N],sz[N],cnt[N],ans=0,color[N],cur_ans=0,n,k;
map<int,int> subtree[N],tree[N];
set<int> occur[N];
pair<int,int> maintain_ans[N];
pair<int,int> min_ans={0,0};
set<int> colors_maintain;
void dfs_sz(int x,int p=-1)
{
  tree[h[x]][color[x]]++;
  sz[x]=1;
  occur[color[x]].insert(h[x]);
  for(auto y:ma[x])
  {
    if(y==p)continue;
    h[y]=h[x]+1;
    dfs_sz(y,x);
    sz[x]+=sz[y];
  }
}
int req_color;
// ans_p+=subtree[h][color[x]];
// step_p+=min(cnt[h]-subtree[h][color[x]],tree[h][color[x]]-subtree[h][color[x]]);
void rem_contro(int he,int co)
{
	maintain_ans[co].first-=subtree[he][co];
	maintain_ans[co].second-=min(cnt[ he]-subtree[he][co],tree[he][co]-subtree[he][co]);
}
void add_contro(int he,int co)
{
	maintain_ans[co].first+=subtree[he][co];
	maintain_ans[co].second+=min(cnt[he]-subtree[he][co],tree[he][co]-subtree[he][co]);
}

void adder(int x,int p)
{
	// color[i] < K
	// if(color[x]<2)
	for(auto col:colors_maintain)
	{
		rem_contro(h[x],col);
	}

  cnt[h[x]]++;
  subtree[h[x]][color[x]]++;
	for(auto col:colors_maintain)
	{
		add_contro(h[x],col);
	}
  for(auto y:ma[x])
  {
    if(y==p)continue;
    adder(y,x);
  }
}


void deleter(int x,int p)
{
	// if(color[x]<2)
	for(auto col:colors_maintain)
	{
		rem_contro(h[x],col);
	}
  cnt[h[x]]--;
  subtree[h[x]][color[x]]--;
	for(auto col:colors_maintain)
	{
		add_contro(h[x],col);
	}

  for(auto y:ma[x])
  {
    if(y==p)continue;
    deleter(y,x);
  }
}


void dfs(int x,int p=-1,bool keep=0)
{
  int big=-1;
  for(auto y:ma[x])
  {
    if(y==p)continue;
    if(big==-1 or sz[big]<sz[y])
      big=y;
  }
  for(auto y:ma[x])
  {
    if(y==p or y==big)continue;
    dfs(y,x);
  }
  // cur_ans=0;
for(auto col:colors_maintain)
{
  maintain_ans[col]={0,0};
}
  if(big!=-1)
  {
    dfs(big,x,1);
  }
  for(auto y:ma[x])
  {
    if(y==p or y==big)continue;
    adder(y,x);    
  }
  

  //Real solving part is this
  // cnt[color[x]]++;
  // ans=max(ans,cnt[color[x]]);
	for(auto col:colors_maintain)
	{
		rem_contro(h[x],col);
	}
  cnt[h[x]]++;
  subtree[h[x]][color[x]]++;
	for(auto col:colors_maintain)
	{
		add_contro(h[x],col);
	}
	if(colors_maintain.find(color[x])!=colors_maintain.end())
	{
		min_ans=min(min_ans,{-maintain_ans[color[x]].first-maintain_ans[color[x]].second,maintain_ans[color[x]].second});
		// min_ans=min(min_ans,{-maintain_ans[0].first-maintain_ans[0].second,maintain_ans[0].second});
		// min_ans=min(min_ans,{-maintain_ans[1].first-maintain_ans[1].second,maintain_ans[1].second});
	}
	else
	{
	  int ans_p=0,step_p=0;
	  // cout<<"NODe "<<x<<" caioo asL ";
	  // for(int h=1;h<=n;h++) // either iterate over all height where their is atleast one of color[x]s
	  for(int h:occur[color[x]]) // either iterate over all height where their is atleast one of color[x]s
	  {
	  	ans_p+=subtree[h][color[x]];
	  	// cout<<subtree[h][color[x]]<<' '<<h<<endl;
	  	step_p+=min(cnt[h]-subtree[h][color[x]],tree[h][color[x]]-subtree[h][color[x]]);
	  	// if(min(cnt[h]-subtree[h][color[x]],tree[h][color[x]]-subtree[h][color[x]])<0)cout<<"Error"<<endl;
	  }
	  min_ans=min(min_ans,{-ans_p-step_p,step_p});
	}
  // cout<<endl;
  // if((ans_p+step_p)>4)
  // {
  	// cout<<"Node "<<x<<' '<<-ans_p-step_p<<' '<<step_p<<endl;
  // }




  if(!keep)
  {
    deleter(x,p);
  }
}

int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin>>n>>k;
  for(int i=0;i<n;i++)cin>>color[i];
bool subtask=1;
  for(int i=1;i<n;i++)
  {
    int x=i,y;
    cin>>y;
    subtask&=(y==(x-1));
    // cout<<y<<' '<<x<<endl;
    ma[y].push_back(x);
  }
  if(subtask)
  {
  	map<int,int> apt;
  	int mx=0;
  	for(int i=n-1;i>=0;i--)
  		mx=max(mx,++apt[color[i]]);
  	cout<<mx<<' '<<0<<endl;
	return 0;
  }
  h[0]=1;
  dfs_sz(0);
  const int SQ=300;
  for(int i=0;i<k;i++)
  {
  	if(occur[i].size()>SQ)
  	{
  		colors_maintain.insert(i);
	  	maintain_ans[i]={0,0};
  	}
  }
  dfs(0);
  cout<<-min_ans.first<<' '<<min_ans.second<<endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...