CF EDU 112 D - Martial Arts Tournament
阿新 • • 發佈:2022-05-12
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; }