绿色通道
高二数学《绿色通道》总共有 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<n≤5×104,
0
<
a
i
≤
3000
0<a_i≤3000
0<ai≤3000,
0
<
t
≤
1
0
8
0<t≤10^8
0<t≤108
输入样例:
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;
}