样例输入:
2 10
1 100
5 5
样例输出:
1
思想
要想在规定的m时间内尽可能多的通过Ak站点,那么就需要尽可能去挑AK时间少的站点去通过。
我们用一个大根堆去维护。
我们给所有的站点按照坐标从近到远排个序,然后我们由近到远去遍历站点。
如果一个站点的AK时间 + 之前遍历过的站点的AK时间 <=m,说明当前站点是一个合法的站点,我们把它计入到答案的贡献中。
反之,如果加上当前站点的AK时间已经大于m了,说明当前站点不可取,我们拿当前站点与 堆定站点对比一下,如果堆定站点AK时间更长,那么就从堆顶弹出,把当前站点加入堆顶。
这个就叫做反悔贪心。
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1E5+7;
struct NODE
{
int x,t; //坐标,时间
}a[N];
bool cmp(NODE a,NODE b)
{
return a.x<b.x;
}
priority_queue<int>q;
int n,m,sum;
signed main()
{
cin>>n>>m; //n个站点,时间限制m
for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].t;
sort(a+1,a+n+1,cmp); //按照坐标从近到远排
for(int i=1;i<=n;i++)
{
if(sum+a[i].x+a[i].t<=m)
{
sum+=a[i].t;
q.push(a[i].t);
}
else if(!q.empty()&&sum-q.top()+a[i].x+a[i].t<=m)
{
sum=sum-q.top()+a[i].t;
q.pop();
q.push(a[i].t);
}
}
cout<<q.size();
return 0;
}