int a[N]; // f[i] 表示前i道题且选择第i道题的所有方案集合,属性: 最短用时 // 状态转移: f[i] = Min(f[ i - m - 1 <= j <= i - 1 ]) + a[i]; // q[]作为单调队列,存储m道题的用时, 队头最小用时 int q[N], f[N]; int n, m;
boolcheck(int limit) { int hh = 0, tt = 0; for (int i = 1; i <= n; ++ i) { // 滑动窗口 if (q[hh] < i - limit - 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 - limit; i <= n; ++ i) if (f[i] <= m) returntrue;
returnfalse; }
intmain() { ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; ++ i) cin >> a[i];
int l = 0, r = n;
// 二分空题段 while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; }