这题的思路和https://ac.nowcoder.com/acm/problem/50439 类似
在我们看来,每一段都存在一个截至区域,首先肯定是要把截至区域按从小到大的顺序排列,这样之前的选择会为后面的选择腾出更多的时间,这个贪心就是可行的。
既然所选需要最多,有些我选择过后,如果当前总和小于截至日期,直接选择,但是后期选择的时候你会发现个问题,如果你选择当前的,结果后期的修理时间比他小的值可能无法在截至日期前完成,那么就会缩小选择区域,那么我们可以用后者替换当前已选择的最大修理时间那个,因为截止时间从小到大排列,把修理时间多的改为少的,可行性会更优。
所以我们只需要弄个优先队列,每次找出已选择的最大修理时间,如果当前修理时间小于它,则可以替换
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+7;
priority_queue<int> pa;
struct node {
int v,s;
}a[maxn];
bool cmp(node a,node b)
{
return a.s<b.s;
}
signed main()
{
int n;
cin>>n;
for (int i=1;i<=n;++i)
{
cin>>a[i].v>>a[i].s;
}
sort(a+1,a+n+1,cmp);///反排序
int cnt=1,ans=a[1].v;
pa.push(a[1].v);
for (int i=2;i<=n;++i)
{
if ((ans+a[i].v)<=a[i].s)///当前可选直接选
{
pa.push(a[i].v);
++cnt;
ans+=a[i].v;
}
else if (a[i].v<pa.top())///如果不可选,则看是否可以使得解更优
{
ans-=pa.top();
pa.pop();
pa.push(a[i].v);
ans+=a[i].v;
}
}
cout<<cnt<<endl;
return 0;
}


京公网安备 11010502036488号