Description
高三数学作业总共有n道题目要写(其实是抄),编号1..n,抄每道题所花时间不一样,抄第i题要花a[i]分钟。由于西西还要准备NOIP,显然不能成天做数学作业。所以西西决定只用不超过t分钟时间抄这个,因此必然有空着的题。每道题要么不写,要么抄完,不能写一半。一段连续的空题称为一个空题段,它的长度就是所包含的题目数。这样应付自然会引起数学老师的愤怒。数学老师发怒的程度(简称发怒度)等于最长的空题段长度。
现在,西西想知道他在这t分钟内写哪些题,才能够尽量降低数学老师的发怒度。由于西西很聪明,你只要告诉他发怒度的数值就可以了,不需输出方案。(Someone:那么西西怎么不自己写程序?西西:我还在抄别的科目的作业……)
Input
第一行为两个整数n,t,代表共有n道题目,t分钟时间。
以下一行,为n个整数,依次为a[1], a[2],… a[n],意义如上所述。
Output
仅一行,一个整数w,为最低的发怒度。
Data Constraint
Hint
60%数据 n<=2000
100%数据 0
Solution
签到题。我们可以二分一个最大连续空段,这样就变成了一个最多隔mid个不选的最小方案,f[i]=min{f[j]}+t[i] (i-mid-1<=j
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) ((x)>(y)?(x):(y))
#define min(x, y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<(0)?(-(x)):(x))
#define INF 0x3f3f3f3f
#define N 100001
#define E 1001
#define L 1001
int queue[N], f[N], t[N];
inline int read() {
int x = 0, v = 1; char ch = getchar();
for(; ch<'0'||ch>'9'; v=(ch=='-')?(-1):(v),ch=getchar());
for(; ch<='9'&&ch>='0'; (x*=10)+=ch-'0',ch=getchar());
return x * v;
}
inline bool check(int n, int m, int mid) {
fill(f, 0);
fill(queue, 0);
int head = 0;
int tail = 0;
queue[tail] = 0;
rep(i, 1, n) {
while (queue[head] < i - mid - 1 && head <= tail) {
head += 1;
}
f[i] = f[queue[head]] + t[i];
while (f[queue[tail]] > f[i] && head <= tail) {
tail -= 1;
}
queue[++ tail] = i;
}
int ans = INF;
rep(i, n - mid, n) {
ans = min(ans, f[i]);
}
return ans <= m;
}
int main(void) {
int n = read();
int m = read();
rep(i, 1, n) {
t[i] = read();
}
int l = 0;
int r = n;
int bobo = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(n, m, mid)) {
r = mid - 1;
bobo = mid;
} else {
l = mid + 1;
}
}
printf("%d\n", bobo);
return 0;
}