[BZOJ1555][HN集训2008]KD之死(贪心+堆)

57 篇文章 0 订阅
14 篇文章 0 订阅

题目描述

传送门

题解

首先考虑没有车、只有两个物品ab的情况
若a放在b上面,那么这个东西的承重量为bt-aw
反之承重量为at-bw
显然若bt-aw>at-bw,即at+aw < <script type="math/tex" id="MathJax-Element-114"><</script>bt-bw的话,a放在b上是更优的

我们把车当做一个必选的物品,并且从上到下选,这样每次只需要考虑新放入的物品的承重量和之前放入的所有物品的重量和
那么应该先按照w+t排序
如果当前的物品为必选的,那么一定要选,如果选不了(之前的重量和大于承重量),那就弹出之前的最大的那个。如果不能弹了就无解
如果当前物品不是必选的,那么能选就选,如果选不了但是之前最大的要比当前的大,就弹出之前的最大的来选这个,否则不管它

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

int n,m;long long maxv;
struct data{long long w,t;bool flag;}a[600005];
long long sum;int ans;
priority_queue <long long> q;

int cmp(data a,data b) {return a.w+a.t<b.w+b.t;}
bool solve()
{
    for (int i=1;i<=n;++i)
    {
        if (a[i].flag)
        {
            while (sum>a[i].t)
            {
                if (q.empty()) return 0;
                sum-=q.top(),q.pop(),--ans;
            }
            sum+=a[i].w,++ans;
        }
        else
        {
            if (!q.empty()&&sum>a[i].t)
                if (q.top()<a[i].w||sum-q.top()>a[i].t)
                    continue;
            if (!q.empty()&&sum>a[i].t)
                sum-=q.top(),q.pop(),--ans;
            sum+=a[i].w,q.push(a[i].w),++ans;
        }
    }
    return 1;
}
int main()
{
    scanf("%d%d%lld",&n,&m,&maxv);
    for (int i=1;i<=n;++i) scanf("%lld%lld",&a[i].w,&a[i].t);
    for (int i=1;i<=m;++i)
    {
        int x;scanf("%d",&x);
        a[x].flag=1;
    }
    sort(a+1,a+n+1,cmp);
    a[++n].flag=1;a[n].t=maxv;
    if (!solve()) puts("Foolish SD!");
    else printf("%d\n",ans-1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值