题解:CF2255D How Long Until Nothing Remains?
这题真简单吧。
不妨先固定操作次数
不妨设
我们希望最终
问题转化为,有价值为
考虑贪心。设
:::info[贪心正确性证明]
设当前未分配的最大价值为
若
若
:::
考察合法的
但是
时间复杂度为
:::success[代码]
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
using ui = unsigned int;
using ull = unsigned long long;
using u128 = unsigned __int128;
using ld = long double;
using pii = pair<int, int>;
const int MAXN = 2e5 + 5;
template<typename T> T lowbit(T x) { return x & -x; }
template<typename T> void chkMin(T &x, T y) { x = y < x ? y : x; }
template<typename T> void chkMax(T &x, T y) { x = x < y ? y : x; }
constexpr int lg2(ll x) { return 63 ^ __builtin_clzll(x); }
constexpr ll bitCeil(ll x) { return x == 1 ? 1ll : 1ll << lg2(x - 1) + 1; }
int tc, n, a[MAXN];
bool check(int k) {
int c = max(k - 30, 0);
priority_queue<int> Q(a + 1, a + n + 1 - c);
for (int i = min(k, 30) - 1; i >= 0 && !Q.empty(); --i) {
int x = Q.top();
Q.pop();
if (x > (1 << i)) {
x -= 1 << i;
Q.emplace(x);
}
}
return Q.empty();
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> tc;
while (tc--) {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
sort(a + 1, a + n + 1);
for (int k = n; k <= n + 30; ++k) {
if (check(k)) {
cout << k << '\n';
break;
}
}
}
return 0;
}
:::