AtCoder Packing Under Range Regulations (贪心 模拟)

题目链接: Packing Under Range Regulations

大致题意

有n个球, 其中第i个球可以放在[l, r]位置, 每个位置只能放一个球.

问: 能否使得n个球都有位置放.

解题思路

模拟 贪心

我们考虑模拟怎么放球最优.

首先我们可以按照区间左端点去排序, 如果左端点相同, 我们肯定先放右端点最小的.

假设当前有四个球 [ 2 , 2 ] , [ 2 , 3 ] , [ 2 , 5 ] , [ 3 , 4 ] [2, 2], [2, 3], [2, 5], [3, 4] [2,2],[2,3],[2,5],[3,4]​​​, 如果我们贪心的按照排序后的顺序放, 我们发现并不是最优的情况. 因为我们可以分配2, 3, 5, 4位置方式放完全部的球.

我们考虑为什么会出现上文的情况?

原因是, 当我把第一个球放到位置2后, 实际上再放球的位置一定≥3, 相当于左区间的限制已经变为了3, 则此时我们应当把第四个球也一起考虑进来.

我们每次应当优先放所有被考虑的球中, 右端点最小的球. 可以采用小顶堆来维护.


那么对于本题, 我们可以用 p o s pos pos​​表示当前放球的位置. 枚举排序后的区间 [ l , r ] [l, r] [l,r]​, 如果此时 p o s = = l pos == l pos==l​​, 我们就需要考虑当前球, 则把当前球的右端点加入堆中即可. 反之表明 p o s < l pos < l pos<l​, 则我们按照堆中顺序, 填充 [ p o s , l ) [pos, l) [pos,l)​​​​区间即可. 填充后再将当前球入堆.

不合法情况: 如果堆中的右端点 小于 当前放球的位置, 则无解.

代码细节: 每次把球入堆后, 记得更新放置位置 p o s = l pos = l pos=l.

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
int main()
{
	int t; cin >> t;
	while (t--) {
		int n; scanf("%d", &n);

		vector<pair<int, int>> v;
		rep(i, n) {
			int l, r; scanf("%d %d", &l, &r);
			v.push_back({ l, r });
		}
		sort(v.begin(), v.end());
		v.push_back({ 0x3f3f3f3f, 0x3f3f3f3f }); //处理最后的球

		priority_queue<int, vector<int>, greater<>> heap; //保存所有的右端点
		bool flag = 1;
		int pos = -1;
		for (auto& [l, r] : v) {
			if (pos == l) heap.push(r);
			else {
				while (pos < l and !heap.empty()) {
					auto op = heap.top(); heap.pop();
					if (op >= pos) pos++;
					else {
						flag = 0;
						goto here;
					}
				}

				pos = l;
				heap.push(r);
			}
		}

		here: puts(flag ? "Yes" : "No");
	}

	return 0;
}

END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逍遥Fau

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

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

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

打赏作者

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

抵扣说明:

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

余额充值