【codevs 2913】建筑抢修

来自Loi_Q的题解:
正解贪心+堆。
先按截稿时间/花费时间从小到大来排一遍序, 因为截稿时间靠前的
肯定要先选,截稿时间相同的肯定要选时间短的。
然后我们建个堆,堆顶是花费时间最大的元素。
① 然后从第一个开始,若当前任务所需时间+之前的总时间小于等于
当前截稿时间,则扔进堆里, ans++。 //能够完成,更新 tot
若大于,这时要从它前面所有任务中选一个花费时间最长的(就是堆
顶元素, 记为 y)和它比较,
②若当前任务所需时间 > y,则不扔进堆中。 //若替换,当前任务仍
然不能完成;
③若当前任务所需时间 < y,则把 y 替换成当前任务。 //当前任务能
够完成, ans 数不变,使得 now 减小,更加优;
这样能保证时间利用率最高,完成更多任务。
正确性证明:
上述;
有没有一种操作,弹出花费时间最大的任务 y,使 tot 减小;
没有
如果后面仍然没有能够完成的,这样会使 ans–;
如果后面有能够完成的,它的时间比 y 大,不优;
它的时间比 y 小,会在③操作中实现。//*

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
priority_queue<ll>q;
int n;
struct work
{
    int len,sto,rest;
}w[150000+5];
bool cmp(work a,work b)
{
    return a.rest<b.rest;
}
int main()
{
    int a,b;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a,&b);
        w[i].len=a;
        w[i].sto=b;
        w[i].rest=b-a;
    }
    sort(w+1,w+1+n,cmp);
    ll now=0,cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(now+w[i].len<=w[i].sto)
        {
            q.push(w[i].len);
            cnt++;
            now+=w[i].len;
        }
        else if(q.top()>w[i].len)//len排序 
        {
            now-=q.top();
            q.pop();
            now+=w[i].len;
            q.push(w[i].len);
        }
    }
    printf("%lld\n",cnt);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值