AtCoder Regular Contest 076 F - Exhausted? (贪心)

题面

在这里插入图片描述

题解

如果只有 l l l 的限制,那么肯定直接按照 l l l 从小到大排序,然后从左边的椅子依次开始填就完了,就是道贪心板题了。

但是这题同时限制了 l l l r r r 怎么办呢,它直接进化成黑题了。

我们不妨先按照 l l l 贪心,然后给 r r r 一个反悔的机会。

有点抽象,具体的做法是:

我们仍然按照 l l l 排序(从小到大,如前文所述),每次选最小的没有被占据的,如果没有这样的位置,那么就考虑把之前的一个人“替换”出来,需要被替换出来的人的 r r r 比当前的 r r r 小(这样替换出来才有更多的选择空间),如果有多个满足要求显然应该替换 r r r 最小的出来。
操作完之后还剩下若干个人(被“替换”出来或是“替换”失败的倒霉蛋),并且此时被占据的位置一定是个前缀,因此我们按(剩余人的) r r r 从大到小排序再贪心即可(从右边的椅子开始填),此时坐不下的人就没办法了。

看到上面的“显然”就知道肯定不是笔者说的, 上面的做法出自wzy大神的讲评,感觉还是很好理解的(我只解释了四个地方)。

因此只需要做 l l l 时用一个小根堆维护 r r r 最小的人,其次要注意一个细节,后面贪心 r r r 的时候不能坐到前面贪 l l l 时坐满的位置。
在这里插入图片描述

CODE

#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define LL long long
#define DB double
#define ENDL putchar('\n')
LL read() {
	LL f=1,x=0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
int n,m,i,j,s,o,k;
struct it{
	int l,r;  it(){l=r=0;}
	it(int L,int R){l=L;r=R;}
}a[MAXN];
bool cmp(it a,it b) {return a.l < b.l;}
bool operator < (it a,it b) {return a.r < b.r;}
bool operator > (it a,it b) {return b < a;}
priority_queue<it,vector<it>,greater<it> > b1;
priority_queue<it> b2;
int main() {
	n = read();m = read();
	for(int i = 1;i <= n;i ++) {
		a[i].l = read();a[i].r = read();
	}
	sort(a + 1,a + 1 + n,cmp);
	int le = 0;
	b1.push(it(0,m+1));
	for(int i = 1;i <= n;i ++) {
		if(le < a[i].l) {
			le ++;
			b1.push(a[i]);
		}
		else {
			if(a[i].r > b1.top().r) {
				b2.push(b1.top());
				b1.pop(); b1.push(a[i]);
			}
			else b2.push(a[i]);
		}
	}
	int ans = 0,le2 = m+1;
	while(!b2.empty()) {
		it t = b2.top(); b2.pop();
		if(le2 > max(t.r,le+1)) le2 --; // Detail!! : Don't disturb the prefix !!
		else ans ++;
	}
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值