后悔贪心法 小Z的AK计划(洛谷 P2107)

小Z的AK计划

题目描述

在小Z的家乡,有机房一条街,街上有很多机房。每个机房里都有一万个人在切题。小Z刚刷完CodeChef,准备出来逛逛。

机房一条街有 n 个机房,第 i 个机房的坐标为 xi ,小Z的家坐标为 0。小Z在街上移动的速度为1,即从 x1 到 x2 所耗费的时间为 |x1 − x2|。 每个机房的学生数量不同,ACM 题目水平也良莠不齐。小Z到达第 i 个机房后,可以花 ti 的时间想题,然后瞬间 AK;当然,也可以过机房而不入。

小Z现在只有 m 个单位时间,之后他就该赶着去打 Codeforces 了。现在他想知道自己最多能在多少个机房 AK,希望你帮帮他。

输入格式

第一行包含两个整数 n,m。

接下来 n 行,每行包含两个整数 xi,ti 。

输出格式

第一行包含一个整数,表示小Z最多能 AK 的机房数量。

输入 #1

2 10
1 100
5 5

输出 #1

1

贪心+优先队列;
1.先把坐标从小到大排序;另外,要AK一个机房,前面的机房时间必须都走过;

2.先把依次路过的机房都去AK,当耗时大于m时,再退掉耗时最大的机房(相当于这个机房不AK,只是路过),直到不大于m;这时可以再往后走,找到最多的AK机房数量;

代码:

#include
#define LL long long
#define pa pair
using namespace std;
priority_queue< LL,vector<LL> >qu;
struct Node{
	LL x,t;	
}an[100100]; 
bool cmp(Node p,Node q){
	return p.x<q.x;
}
int n,ans,mmax;
LL m,sum;
int main(){
	scanf("%d%lld",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld%lld",&an[i].x,&an[i].t);
	sort(an+1,an+n+1,cmp);
	for(int i=1;i<=n;i++){
		sum+=an[i].x-an[i-1].x+an[i].t;
		qu.push(an[i].t);
		ans++;
		while(!qu.empty()&&sum>m){
			sum-=qu.top();
			qu.pop();
			ans--;
		}
		mmax=max(ans,mmax);
		if(sum>m) break;//说明这个点已经不能往后走了 
	}
	printf("%d\n",mmax); 
	return 0;
}

你可能感兴趣的:(#,贪心,贪心)