答案显然具有单调性,所以可以考虑二分答案来。
对于二分得到的答案段数,的时候设表示区间为合法区间且写了位置的作业的最小花费。则有方程,这个可以用单调队列维护。
那么对于这段区间取个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); }