LYK喜欢逛街。
但是LYK时间有限,只有T个单位时间。
LYK从1号店出发,从1号店走到第i号店需要花费 ai 个单位的时间,这些店形成了一条直线,因此LYK从i号店到i+1号店花费的时间为 ai+1−ai 。若选择进去逛,则需要需要花费 bi 的时间。对于第i家店,LYK对其有个评估值 ci ,表示自己是否喜欢这家店。
LYK想在有限的时间内,逛无限的街,当然这是不可能的。
它有个目标,将走进去逛的店中 ci 的和加起来,要使得这个值 ≥ k,在此基础上,能逛的店越多越好。
它想知道最多能逛多少店。
若无法满足LYK的要求,输出-1。
Input
第一行三个整数n(1<=n<=100000),T(1<=T<=10^9),k(0<=k<=n)。
接下来一行n个数,表示ai(a1=0,a1< a2 <…< an < =10^9)。
接下来一行n个数,表示bi(1 < =bi < =10^9)。
接下来一行n个数,表示ci(0 <=ci < =1)。
Output
一行表示答案。
Input示例
4 11 1
0 1 2 10
1 1 1 1
0 0 0 1
Output示例
1
题解
我们发现肯定从左往右走,不会回头。
于是我们从左往右扫。
定义两个大根堆:q1,q2;一个小根堆:q3
q1维护k个bi最小值,q2维护逛的店,q3维护不逛的店。
每次维护,使得q1与q2的权值和<=T
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
priority_queue<int,vector<int> >q1,q2;
priority_queue<int,vector<int>,greater<int> >q3;
int n,k,a[100005],b[100005],c[100005],ans;
ll T,t1,t2,t3;
int main()
{
n=read();T=read();k=read();ans=-1;
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++) b[i]=read();
for (int i=1;i<=n;i++) c[i]=read();
for (int i=1;i<=n;i++)
{
if (c[i])
{
q1.push(b[i]);t1+=b[i];
if (q1.size()>k)
{
t1-=q1.top();
q2.push(q1.top());
t2+=q1.top();
q1.pop();
}
}
else
{
q2.push(b[i]);
t2+=b[i];
}
if (q1.size()<k) continue;
if (t1+a[i]>T) continue;
ll rest=T-t1-a[i];
while (!q2.empty()&&!q3.empty())
{
if (q2.top()>q3.top())
{
t2+=q3.top()-q2.top();
q3.push(q2.top());
q2.pop();
q2.push(q3.top());
q3.pop();
}
else break;
}
while (!q2.empty())
{
if (t2<=rest) break;
t2-=q2.top();
q3.push(q2.top());
q2.pop();
}
while (!q3.empty())
{
if (t2+q3.top()>rest) break;
t2+=q3.top();
q2.push(q3.top());
q3.pop();
}
if (t2<=rest) ans=max(ans,k+(int)q2.size());
}
printf("%d",ans);
return 0;
}