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;
}
posted @ 2021-12-22 21:11  Suzt_ilymtics  阅读(49)  评论(0编辑  收藏  举报