제출 #1188375

#제출 시각아이디문제언어결과실행 시간메모리
1188375esomerTeam Coding (EGOI24_teamcoding)C++20
100 / 100
163 ms132592 KiB
#include <bits/stdc++.h>

using namespace std;

const int B = 300;

vector<int> bigColors; //colors with more than B people.
vector<int> anc; //the highest ancestor of each color.
vector<vector<int>> all; //all the people with each color.
vector<int> depth, maxDepth;
vector<int> cntDepth, cntColor;
vector<vector<int>> depthCol; //the number of nodes at each depth for the bigColors.
pair<int, int> ans = {0, 0};

void getDepth(int x, vector<vector<int>>& adj) {
	maxDepth[x] = depth[x];
	for (int node : adj[x]) {
		depth[node] = depth[x] + 1;
		getDepth(node, adj);
		maxDepth[x] = max(maxDepth[x], maxDepth[node]);
	}
}

void DFS(int x, vector<vector<int>>& adj, vector<int>& l) {
	int c = l[x];
	cntDepth[depth[x]]++;
	cntColor[c]++;
	if ((int)all[c].size() <= B) {
		if (anc[c] == -1) {
			anc[c] = x;
			//I iterate over all of them.
			int cntColorBefore = cntColor[c];
			vector<int> before((int)all[c].size(), 0); //the number of nodes of each interesting depth before, i don't repeat depths.
			for (int i = 0; i < (int)all[c].size(); i++) {
				int y = all[c][i];
				if (depth[y] <= depth[x] || (i > 0 && depth[y] == depth[all[c][i-1]])) continue;
				before[i] = cntDepth[depth[y]];
			}
			for (int node : adj[x]) {
				DFS(node, adj, l);
			}
			pair<int, int> res = {1, 0};
			for (int i = 0; i < (int)all[c].size(); i++) {
				int y = all[c][i];
				if (depth[y] <= depth[x] || (i > 0 && depth[y] == depth[all[c][i-1]])) continue;
				int total = cntDepth[depth[y]] - before[i]; //total #nodes with depth[y] in the subtree.
				int numColor = 1; //total #node of color c with depth[y].
				int mx = i;
				for (int j = i+1; j < (int)all[c].size(); j++) {
					if (depth[all[c][j]] == depth[y]) numColor++;
					else break;
					mx = j;
				}
				i = mx;
				res.first += min(numColor, total);
			}
			res.second = res.first - 1 - (cntColor[c] - cntColorBefore);
			if (res.first > ans.first) ans = res;
			else if (res.first == ans.first) ans.second = min(ans.second, res.second);
			anc[c] = -1;
		} else {
			for (int node : adj[x]) {
				DFS(node, adj, l);
			}
		}
	} else {
		if (anc[c] == -1) {
			anc[c] = x;
			vector<int> before;
			for (int i = depth[x]+1; i <= maxDepth[x]; i++) {
				before.push_back(cntDepth[i]);
			}
			int cntColorBefore = cntColor[c];
			for (int node : adj[x]) {
				DFS(node, adj, l);
			}
			pair<int, int> res = {1, 0};
			for (int i = depth[x] + 1; i <= maxDepth[x]; i++) {
				int total = cntDepth[i] - before[i - (depth[x] + 1)];
				int numColor = depthCol[c][i];
				res.first += min(total, numColor);
			}
			res.second = res.first - 1 - (cntColor[c] - cntColorBefore);
			if (res.first > ans.first) ans = res;
			else if (res.first == ans.first) ans.second = min(ans.second, res.second);
			anc[c] = -1;
		} else {
			for (int node : adj[x]) {
				DFS(node, adj, l);
			}
		}
	}
	//I still have to update anc.
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	int N, K; cin >> N >> K;
	vector<int> l(N);
	all.resize(K);
	for (int i = 0; i < N; i++) {
		cin >> l[i];
		all[l[i]].push_back(i);
	}
	for (int i = 0; i < K; i++) {
		if ((int)all[i].size() > B) bigColors.push_back(i);
	}
	vector<vector<int>> adj(N);
	for (int i = 1; i < N; i++) {
		int p; cin >> p;
		adj[p].push_back(i);
	}
	depth.assign(N, 0);
	maxDepth.assign(N, 0);
	getDepth(0, adj);
	depthCol.resize(K);
	for (int i = 0; i < K; i++) {
		vector<pair<int, int>> nw;
		for (int x : all[i]) nw.push_back({depth[x], x});
		sort(nw.begin(), nw.end());
		all[i].clear();
		for (pair<int, int> pr : nw) all[i].push_back(pr.second);
		if ((int)all[i].size() > B) {
			depthCol[i].assign(N, 0);
			for (int x : all[i]) depthCol[i][depth[x]]++;
		}
	}
	anc.assign(K, -1);
	cntDepth.assign(N, 0);
	cntColor.assign(K, 0);
	DFS(0, adj, l);
	cout << ans.first << " " << ans.second << "\n";
}
#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...