제출 #1199492

#제출 시각아이디문제언어결과실행 시간메모리
1199492cxijsijsjsykTeam Coding (EGOI24_teamcoding)C++20
81 / 100
4094 ms48128 KiB
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<cassert>
using namespace std;
vector<int> edges[100005];
pair<int, int> times[100005];
int depth[100005];
int col[100005]; int cnt = 1;
vector<int> depthtimes[100005];
vector<int> nwcol[100005];
map<int, int> dwcol[100005];
map<int, int> stdepth; map<int, int> cldepth;
int bestans = 0; int bestswap = 1e9;
void dfs(int n, int d) {
	times[n].first = cnt++;
	depth[n] = d;
	for (auto c : edges[n]) {
		dfs(c, d+1);
	}
	times[n].second = cnt++;
}

void find(int n, int cl, bool found) {
	if (found) {
		stdepth[depth[n]]++;
		if (col[n] == cl) cldepth[depth[n]]++;
	}
	for (auto c : edges[n]) {
		if (col[n] == cl) find(c, cl, true);
		else find(c, cl, found);	
	}
	if (col[n] == cl && !found) {
		int curans = 0; int curswap = 0;
		for (auto p : stdepth) {
			curans += min(p.second, dwcol[cl][p.first]);
			curswap += max(0, min(p.second, dwcol[cl][p.first])-cldepth[p.first]);
		}
		if (bestans == curans+1) {
			bestswap = min(bestswap, curswap);
		}
		else if (bestans < curans+1) {
			bestans = curans+1;
			bestswap = curswap;
		}
		stdepth.clear(); cldepth.clear();
	}
}

int main() {
	int n, k; cin>>n>>k;
	for (int i = 0; i < n; i++) cin>>col[i];
	
	for (int i = 1; i < n; i++) {
		int x; cin>>x;
		edges[x].push_back(i);
	}
	
	dfs(0, 0);
	if (k < sqrt(n)) {
		for (int i = 0; i < n; i++) {
			dwcol[col[i]][depth[i]]++;
		}
		for (int i = 0; i < k; i++) {
			find(0, i, false);
		}
		cout<<bestans<<" "<<bestswap<<endl;
		return 0;
	}

	for (int i = 0; i < n; i++) {
		depthtimes[depth[i]].push_back(times[i].first);
	}
	for (int i = 0; i <= n; i++) {
		sort(depthtimes[i].begin(), depthtimes[i].end());
	}
	for (int i = 0; i < n; i++) {
		nwcol[col[i]].push_back(i);
	}
	
	for (int i = 0; i < n; i++) {
		map<int, int> used;
		map<int, int> swapped;
		int curans = 0;
		int curswap = 0;
		for (auto j : nwcol[col[i]]) {
			if (j == i || depth[j] <= depth[i]) continue;
			int up = upper_bound(depthtimes[depth[j]].begin(), depthtimes[depth[j]].end(), times[i].second)-depthtimes[depth[j]].begin();
			int low = lower_bound(depthtimes[depth[j]].begin(), depthtimes[depth[j]].end(), times[i].first)-depthtimes[depth[j]].begin();
			assert(up-low>=0);
			if (up-low-used[depth[j]]>0) {
				used[depth[j]]++;
				curans++;
				swapped[depth[j]]++;
				curswap++;
			}
			if (times[i].first < times[j].first && times[j].second < times[i].second) {
				if (swapped[depth[j]]>0) {
					swapped[depth[j]]--;
					curswap--;	
				}
			}
		}
		if (bestans == curans+1) {
			bestswap = min(bestswap, curswap);
		}
		else if (bestans < curans+1) {
			bestans = curans+1;
			bestswap = curswap;
		}
	}
	cout<<bestans<<" "<<bestswap<<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...