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