【51Nod1689】逛街

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值