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

来源:互联网 发布:淘宝图片下载器破解版 编辑:程序博客网 时间:2024/05/01 14:48

题目描述

传送门

题解

首先考虑没有车、只有两个物品ab的情况
若a放在b上面,那么这个东西的承重量为bt-aw
反之承重量为at-bw
显然若bt-aw>at-bw,即at+aw<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
原创粉丝点击