CF EDU 112 D - Martial Arts Tournament

D - Martial Arts Tournament

枚举

不能枚举 x, y ,但是可以枚举集合大小,设三个集合大小分别为 \(2^i,2^j,2^k\), 枚举 i,j 即可,复杂度为 \(O(nlognlogn)\)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;

const int N = 2e5 + 10;
int n;
int mp[N];

int solve(int w1, int w2)
{
	int res = 0, sum = 0, i = 1;
	//第一个集合要加多少
	for ( ; i <= n; i++)
	{
		if (sum + mp[i] > w1)
			break;
		sum += mp[i];
	}
	res += w1 - sum;
	//第二个集合要加多少
	sum = 0;
	for ( ; i <= n; i++)
	{
		if (sum + mp[i] > w2)
			break;
		sum += mp[i];
	}
	res += w2 - sum;
	
	int w3 = 1;
	sum = 0;
	for ( ; i <= n; i++)
		sum += mp[i];
	//原来 n 个数中还剩 sum 个,第三个集合大小应是 >= sum 的 2 的幂
	while(w3 < sum)
		w3 <<= 1;
	res += w3 - sum;
	return res;
}
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n;
		fill(mp, mp + n + 2, 0);
		for (int i = 1; i <= n; i++)
		{
			int x;
			cin >> x;
			mp[x]++;
		}
		int ans = 1e9;
		for (int i = 0; (1 << i) <= n; i++)
			for (int j = 0; (1 << j) <= n; j++)
				ans = min(ans, solve(1 << i, 1 << j));
		cout << ans << endl;
	}
	return 0;
}

posted @ 2022-05-12 20:09  hzy0227  阅读(12)  评论(0编辑  收藏  举报