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;
}