CF1515C Phoenix and Towers (贪心)

题目链接: Phoenix and Towers

大致题意

给你n个数, 要求你把这些数字分成m组, 使得任意两组之间的差值不超过x.

解题思路

贪心 这有点像之前cf的一个B题, 大概是说放积木, 问最少能放几层.

我们遍历n个数字, 每次把当前这个数字放到总和最小的组里即可.

因为我们最后要求任意两组之前的差值尽可能的小, 相当于让m组数尽可能的平均. 我们贪心去做即可.

到这里你发现, 可能我这样的做法并不会使得这m组数尽可能的平均, 因为我们也没有排序.

给出一个例子: 对于3个数, 分成2组的情况. 1 2 7

一开始的两组的情况为{ 0, 0 }, 那么第一个数字, 变为{ 0, 1 }, 再放完第二个数字, 变为{ 1, 2 }. 再放第三个数字, 变为 { 2, 8 }. 但是很明显, 我们可以构造出 { 3, 7 }的方法, 这样会更优.

但是本题的特点是, 如果要求的差值是x, 数字给的范围为[1, x], 也就是说, 不会有任意两个数字, 使得他们之间的差值 ≥ x, 因此如果我们每次直接以上述贪心的方式去放, 也不会使得他们之间的差值超过x.

这里可以采用反证法, 如果放完val后, 此时存在两组a和b, 满足其差值大于x, 那么说明val一定可以放在较小的那组数中, 使得差值≤ x, 与我们最开始的贪心做法相矛盾.

由上述推到我们也可以证明, 本题是一定存在解的, 并不存在 “NO” 的情况.

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1E5 + 10;
int res[N];
int main()
{
	int t; cin >> t;
	while (t--) {
		priority_queue<PII, vector<PII>, greater<>> q; //构造小顶堆
		int n, m, k; scanf("%d %d %d", &n, &m, &k); 

		rep(i, m) q.push({ 0, i }); //第二维是组数的下标
		rep(i, n) {
			int x; scanf("%d", &x);
			auto op = q.top(); q.pop();
			op.first += x; res[i] = op.second;
			q.push(op);
		}
		puts("YES");
		rep(i, n) printf("%d%c", res[i], " \n"[i == n]);
	}
	return 0;
}

END

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值