高二数学《绿色通道》总共有 nn
道题目要抄,编号 1,2,…,n1,2,…,n
,抄第 ii
题要花 aiai
分钟。小 Y 决定只用不超过 tt
分钟抄这个,因此必然有空着的题。每道题要么不写,要么抄完,不能写一半。下标连续的一些空题称为一个空题段,它的长度就是所包含的题目数。这样应付自然会引起马老师的愤怒,最长的空题段越长,马老师越生气。现在,小 Y 想知道他在这 tt
分钟内写哪些题,才能够尽量减轻马老师的怒火。由于小 Y 很聪明,你只要告诉他最长的空题段至少有多长就可以了,不需输出方案。输入格式第一行为两个整数 n,tn,t
。第二行为 nn
个整数,依次为 a1,a2,…,ana1,a2,…,an
。输出格式输出一个整数,表示最长的空题段至少有多长。数据范围0<n≤5×1040<n≤5×104
,
0<ai≤30000<ai≤3000
,
0<t≤1080<t≤108
输入样例:17 11
6 4 5 2 5 3 4 5 2 3 4 5 2 3 6 3 5
输出样例:3
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50010, INF = 1e9;
int q[N];
int w[N], f[N];
int n, m;
bool check(int k){
int hh = 0, tt = 0;
for (int i = 1; i <= n; i ++){
if (hh <= tt && q[hh] < i - k - 1) hh ++;
f[i] = f[q[hh]] + w[i];
while(hh <= tt && f[q[tt]] >= f[i]) tt --;
q[++ tt] = i;
}
int res = INF;
for (int i = n - k; i <= n; i ++) res = min(res, f[i]);
return res <= m;
}
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++) scanf("%d", &w[i]);
int l = 0, r = n;
while(l < r){
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r << endl;
return 0;
}