bzoj 2802: [Poi2012]Warehouse Store 贪心+优先队列

24 篇文章 0 订阅

题意

有一家专卖一种商品的店,考虑连续的n天。
第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择满足顾客的要求,或是无视掉他。
如果要满足顾客的需求,就必须要有足够的库存。问最多能够满足多少个顾客的需求。
n<=250,000

分析

一开始的想法是,f[i]表示第i天剩下的钱,把所有顾客排序后,每次选花费最小的顾客x,看是否能满足,若能满足则选并把f[x+1..n]减去花费的钱。可以用线段树来维护。
没有打便去搜了一下题解,发现这样做是不行的,我也不知道为毛。。。

正解是枚举每一天,若能选则选并扔进大根堆,否则就看堆顶元素是否大于b[i],是的话就不选堆顶选b[i]。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define N 250005
using namespace std;

struct data
{
    int id,w;

    bool operator < (const data &a) const
    {
        return w<a.w;
    }
};

int n,a[N],b[N],cho[N];
priority_queue <data> q;

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    ll ret=0;
    int ans=0;
    for (int i=1;i<=n;i++)
    {
        ret+=a[i];
        if (b[i]<=ret)
        {
            data u;u.id=i;u.w=b[i];
            ret-=b[i];ans++;q.push(u);
        }else if (!q.empty()&&q.top().w>b[i])
        {
            data u;u.id=i;u.w=b[i];
            ret+=q.top().w-b[i];q.pop();q.push(u);
        }
    }
    while (!q.empty())
    {
        cho[q.top().id]=1;
        q.pop();
    }
    printf("%d\n",ans);
    for (int i=1;i<=n;i++)
        if (cho[i]) printf("%d ",i);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值