题意

  • 有n个建筑,每个建筑有修理花费时间t1和deadline t2,最多能修理几个?

思路

  • 贪心,先修deadline早的或先修时间短的都会有问题
  • 早的{(10,10),(3,11),(2,11)}
  • 短的{(1,10),(2,10),(3,3)}
  • 故考虑新的贪心策略,在deadline一定的情况下,我们希望尽可能修时间短的,同样的,在deadline为9的时候如果是{3,3,3},但是在deadline为10的时候新增了1个耗时为2的,我们会扔掉一个耗时为3的,使序列变为{3,3,2}这样子可以为后面的任务腾出更多时间
  • 所以,对于所有的任务,按照ddl时间升序排序,遍历的时候如果当前时间+新增任务时间<新增ddl,就加入该任务,同时维护一个大顶堆,记录选择了的任务,如果剩余空间不够直接加入新增任务,但是新增任务的消耗时间<堆顶,就弹出堆顶,加入新增,最终堆的大小就是总共可完成的任务个数

AC代码

#include<bits/stdc++.h>
using namespace std;

typedef struct{
    long long t1,t2;
}H;
H a[202020];
bool cmp(H a,H b){
    return a.t2<b.t2;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lld%lld",&a[i].t1,&a[i].t2);
    }
    sort(a,a+n,cmp);
    priority_queue<long long ,vector<long long>,less<long long>>b;
    long long now=0;
    for(int i=0;i<n;i++){
        if(b.empty()||now+a[i].t1<a[i].t2){
            b.push(a[i].t1);
            now+=a[i].t1;
        }else if(a[i].t1<b.top()){
            now-=b.top();
            b.pop();
            now+=a[i].t1;
            b.push(a[i].t1);
        }
    }
    printf("%d",b.size());
    return 0;
}