Atcoder [arc076F] Exhausted

Description

机房里有M台电脑排成一排,第i台电脑的坐标是正整数i。

现在有N个OIer进入了机房,每个OIer需要一台电脑来学tui习ji,同时每个OIer对自己电脑所处的坐标范围有一个要求区间。第i个OIer希望自己的电脑的位置≤Li或≥Ri。自然,一台电脑只能给一个OIer使用,不然会发生友♂好的跤♂流

显然,有可能这个机房无法满足所有OIer的需求。这时老师就会在机房中增加电脑。增加的电脑可以位于任意的实数位置。你需要帮老师计算一下,老师最少加几台电脑,才可以满足所有OIer的需求?


Input

    第一行两个整数N,M

    接下来N行,每行两个整数Li,Ri

Output

    输出最小需要增加的电脑数量

Solution

贪心。
将询问按l,r作为第一、二关键字从小到大排序。
优先插进左端点,并恰好插满左端点(不能大于查询的l)
占据左边的端点的询问的丢进小根堆的优先队列。
记录一个tot表示用了1到tot号电脑。

  1. 若tot小于 L i L_i Li,直接丢进优先队列。
  2. 若tot等于 L i L_i Li,将优先队列中右端点最小的弹出来扔到右边。

因为记录的是向右的标记(>=x)
最后从后往前ans=max(ans,后缀和-后面已有的电脑数)


Code

#include<bits/stdc++.h>
using namespace std;
struct data{
	int l,r;
	bool operator <(const data &v)const{
		if(l!=v.l) return l<v.l;
		return r<v.r;
	}
}a[200010];
priority_queue<int>q;
int b[200010],n,m;
int main(){
	int x,y,tot=0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	scanf("%d%d",&a[i].l,&a[i].r);
	for(int i=1;i<=m;i++) b[i]=-1;
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		//cout<<i<<" "<<a[i].l<<" "<<a[i].r<<" "<<q.size()<<endl;
		if(a[i].l==0){
			b[a[i].r]++; 
			continue;
		}
		if(a[i].l==tot){
			int x=q.top();
			q.pop();
			//cout<<"kk"<<u.l<<" "<<u.r<<" "<<b[u.l]<<" "<<b[u.r]<<endl;
			b[-x]++;
			q.push(-a[i].r);
			continue;
		}
		//cout<<"sss"<<a[i].l<<" "<<b[a[i].l]<<endl;
		b[++tot]++;
		q.push(-a[i].r);
	}
	int ans=0,sum=0;
	for(int i=m+1;i>-1;i--){
		sum+=b[i];
		ans=max(ans,sum);
	//	cout<<b[i]<<endl;
	}
	printf("%d",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值