维护三个堆,分别代表必须取的k个b[i]最小的c[i]=1的商店、还能额外去的商店、暂时不去的商店。
从左到右遍历,如果c[i]=1,则加入堆1,否则加入堆2。对堆2和堆3进行维护,保证堆2中的数量在允许范围内最多。
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100100;
int a[MAXN],b[MAXN],c[MAXN];
priority_queue<int> need,acan,rem;
int main()
{
long long n,t,k,i,ans,needsum,acansum,tmp;
while(~scanf("%lld%lld%lld",&n,&t,&k))
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
scanf("%d",&b[i]);
for(i=1;i<=n;i++)
scanf("%d",&c[i]);
ans=-1;
needsum=acansum=0;
for(i=1;i<=n;i++)
{
if(c[i])
{
need.push(b[i]);
needsum+=b[i];
if(need.size()>k)
{
tmp=need.top();
needsum-=tmp;
need.pop();
acan.push(tmp);
acansum+=tmp;
}
}
else
{
acan.push(b[i]);
acansum+=b[i];
}
if(need.size()<k||needsum+a[i]>t)
continue;
while(!acan.empty()&&!rem.empty()&&acan.top()>-rem.top())
{
tmp=acan.top();
acan.pop();
acansum-=tmp;
acansum+=-rem.top();
acan.push(-rem.top());
rem.pop();
rem.push(-tmp);
}
while(!rem.empty()&&a[i]+needsum+acansum-rem.top()<=t)
{
tmp=-rem.top();
rem.pop();
acan.push(tmp);
acansum+=tmp;
}
while(!acan.empty()&&a[i]+needsum+acansum>t)
{
tmp=acan.top();
acan.pop();
acansum-=tmp;
rem.push(-tmp);
}
if(need.size()==k&&(int(need.size()+acan.size()))>ans)
ans=need.size()+acan.size();
}
printf("%lld\n",ans);
}
}