答案显然具有单调性,所以可以考虑二分答案来。
对于二分得到的答案段数,
的时候设
表示区间
为合法区间且写了位置
的作业的最小花费。则有方程
,这个可以用单调队列维护。
那么对于这段区间取个min然后和t对比就可以确认二分出来的答案是否可行了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 200010;
const int inf = 0x3f3f3f3f;
int n, t, a[N], f[N];
deque<int>q;
bool check(int m) {
memset(f, 0, sizeof(f));
while(!q.empty()) q.pop_back();
q.push_back(0);
for(int i = 1; i <= n; ++i) {
while(!q.empty() && i - q.front() - 1 > m) q.pop_front();
f[i] = f[q.front()] + a[i];
while(!q.empty() && f[i] < f[q.back()]) q.pop_back();
q.push_back(i);
}
int ans = inf;
for(int i = n; i >= n - m; --i) ans = min(ans, f[i]);
return ans <= t;
}
int main() {
scanf("%d%d", &n, &t);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
int l = 0, r = n, ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n", ans);
} 
京公网安备 11010502036488号