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

来源:互联网 发布:惠普427网络打印机驱动 编辑:程序博客网 时间:2024/06/13 22:52

题意

有一家专卖一种商品的店,考虑连续的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 250005using 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;}
0 0