제출 #1176747

#제출 시각아이디문제언어결과실행 시간메모리
1176747nguyenkhangninh99Team Coding (EGOI24_teamcoding)C++20
100 / 100
380 ms42472 KiB


#include <bits/stdc++.h>
using namespace std;

#define pp pair <int, int>
#define fi first
#define se second

const int maxn = 3e5 + 9, blocksz = 320;

int n, k, c[maxn], h[maxn], sz[maxn];
int in[maxn], out[maxn], timedfs = 0;

vector<int> adj[maxn], pos[maxn];
vector<int> large, small;

int mark[maxn];

pp res = {1, 0};

pp cmp(pp A, pp B){
	if(A.fi > B.fi) return A;
	if(A.fi < B.fi) return B;
	if(A.se <= B.se) return A;
	return B;
}

void dfs(int u){
	in[u] = ++timedfs;
	for(int v: adj[u]){
		h[v] = h[u] + 1;
		dfs(v);
	}
	out[u] = timedfs;
}

int cur, mx; 
int cnt_color[maxn], cnt[maxn], mp[maxn];
pp ans;

void dfs_color(int u){
	if(c[u] == cur){
		cnt_color[h[u]]++;
		cnt[u]++;
	}
	for(int v: adj[u]){
		dfs_color(v);
		cnt[u] += cnt[v];
	}
}


void dfs4(int u){
	if(mp[h[u]] < cnt_color[h[u]]) ans.fi++;
	mp[h[u]]++;
    mx = max(mx, h[u]);
	for(int v: adj[u]) dfs4(v);
}

void dfs3(int u){
	if(c[u] == cur){
		ans.fi = mx = 0;
		dfs4(u);
		ans.se = ans.fi - cnt[u];
		res = cmp(res, ans);
		for(int i = h[u]; i <= mx; i++) mp[i] = 0;
	}
	else for(int v: adj[u]) dfs3(v);
}

void solve_large(int color){
	cur = color;
	for(int i = 1; i <= n; i++) cnt[i] = cnt_color[i] = 0;
	dfs_color(1);
	dfs3(1);
}

vector<int> L[maxn];

void dfs_merge(int u){
	if(adj[u].size () == 0){
		pos[u].push_back(1);
		return;
	}
	for(int v: adj[u]){
		dfs_merge (v);
		if(pos[v].size() > pos[u].size()) swap (pos[u], pos[v]);
		for(int z = 0; z < pos[v].size(); z++) pos[u][z] += pos[v][z];
		pos[v].clear ();
	}
	pos[u].insert(pos[u].begin(), 1);
	ans.fi = ans.se = 0;
	for (int i = 0; i < L[c[u]].size(); i++){
		int x = L[c[u]][i];
		if (h[x] < h[u]) continue;
		int cnt_node = 1, j = i + 1;
		int in_subtree = (in[u] <= in[x] && in[x] <= out[u]);
		while (j < L[c[u]].size () && h[L[c[u]][j]] == h[x]){
			cnt_node++;
			int y = L[c[u]][j];
			if (in[u] <= in[y] && in[y] <= out[u]) in_subtree++;
			j++;
		}
		if (h[x] - h[u] < pos[u].size () && h[x] - h[u] >= 0){
			ans.fi += min(cnt_node, pos[u][h[x] - h[u]]);
			ans.se += min(cnt_node, pos[u][h[x] - h[u]]) - in_subtree;
		}
		i = j - 1;
	}
	res = cmp(res, ans);
}

bool cmp_depth(int u, int v){
	return h[u] < h[v];
}


signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	cin >> n >> k;
	for (int i = 1; i <= n; i++){
		cin >> c[i]; 
        sz[c[i]]++;
	}

	for (int i = 0; i < k; i++){
		if(sz[i] >= blocksz) large.push_back(i);
		else if(sz[i]){
			small.push_back(i);
			mark[i]++;
		}
	}

	for (int i = 2; i <= n; i++){
		int p; cin >> p;
		adj[p + 1].push_back(i);
	}
	
    dfs(1);
	for(int i: large) solve_large(i);

	for(int i = 1; i <= n; i++){
		if(mark[c[i]] == 0) continue;
		L[c[i]].push_back(i);
	}

	for(int i = 0; i < k; i++) if(L[i].size()) sort(L[i].begin(), L[i].end(), cmp_depth);
	dfs_merge(1);

	cout << res.fi << " " << res.se;
}
#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...