单调队列优化DP+二分——绿色通道

10 篇文章 0 订阅

绿色通道

高二数学《绿色通道》总共有 n 道题目要抄,编号 1,2,…,n,抄第 i 题要花 ai 分钟。

小 Y 决定只用不超过 t 分钟抄这个,因此必然有空着的题。

每道题要么不写,要么抄完,不能写一半。

下标连续的一些空题称为一个空题段,它的长度就是所包含的题目数。

这样应付自然会引起马老师的愤怒,最长的空题段越长,马老师越生气。

现在,小 Y 想知道他在这 t 分钟内写哪些题,才能够尽量减轻马老师的怒火。

由于小 Y 很聪明,你只要告诉他最长的空题段至少有多长就可以了,不需输出方案。

输入格式
第一行为两个整数 n,t。

第二行为 n 个整数,依次为 a1,a2,…,an。

输出格式
输出一个整数,表示最长的空题段至少有多长。

数据范围
0 < n ≤ 5 × 1 0 4 0<n≤5×10^4 0<n5×104,
0 < a i ≤ 3000 0<a_i≤3000 0<ai3000,
0 < t ≤ 1 0 8 0<t≤10^8 0<t108
输入样例:
17 11
6 4 5 2 5 3 4 5 2 3 4 5 2 3 6 3 5
输出样例:
3

题解:

这道题显然是满足二分性的,所以我们这道题和上一道题只是多套了一个二分,状态方程还是那么设,f[i]表示前i个前题并且没有选第i个题,并且这道题有小细节不同,烽火台那道题我们可以连续k个烽火台必须选择其中一个,而这道题是间隔的,这意味着我们第i个可以不选,但是我们第i-1个必须选,所以这道题我们区间端点可以不选,而我们上一题区间端点必须选。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int a[N],q[N],f[N],n,m;
int check(int lim)
{
    int hh=0,tt=0;
    for(int i=1;i<=n;i++){
        if(hh<=tt&&q[hh]<i-lim-1) hh++;
        f[i]=f[q[hh]]+a[i];
        while(hh<=tt&&f[q[tt]]>=f[i]) tt--;
        q[++tt]=i;
    }
    for(int i=n-lim;i<=n;i++){
        if(f[i]<=m) return 1;
    }
    return 0;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    int l=0,r=n;
//    cout<<"---"<<endl;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    cout<<l<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值