CF748E Santa Claus and Tangerines 题解
Solution
通过观察发现,每次操作一定是将最大的一个或多个橘子分成两部分。
而 \(a_i \le 10^7\),我们考虑用一个桶记录,然后从大向小遍历,遇到大的就把它分成两部分,在这个过程中求出最优解。
我们设分发的最小的橘子瓣数为 \(l\),现在枚举到了 \(i\),在 \([l,i]\) 这段区间中有 \(n\) 瓣橘子。
对于每一个位置 \(i\),我们先考虑能不能让 \(l\) 在满足 \(n \ge K\) 的情况下变得尽可能大(代码中其实是找到了这个位置后面一个位置)
然后如果 \(i\) 分成两部分后的较大一部分比 \(l\) 小,那么再分已经没有意义了,\(l-1\) 就是我们求的答案,输出完退出即可。
分的时候讨论一下奇偶性暴力分就行。
注意每次分时 \(n\) 会增加 \(f_i\) 瓣橘子。
注意 \(i\) 只能枚举到 \(2\)。
如果最后 \(n \ge K\) 输出 1
,否则证明无解输出 -1
。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 1e7 + 10;
int n, K, ans = MAXN;
int f[MAXN];
signed main() {
cin >> n >> K;
for(int i = 1, x; i <= n; ++i) cin >> x, f[x]++;
int l = 0;
for(int i = MAXN - 10; i >= 2; --i) {
while(n >= K) n -= f[l++];
if((i + (i & 1) >> 1) < l) return printf("%lld\n", l - 1), 0;
if(i & 1) f[i >> 1] += f[i], f[(i >> 1) + 1] += f[i];
else f[i >> 1] += 2 * f[i];
n += f[i];
}
if(n >= K) puts("1");
else puts("-1");
return 0;
}