题解里我看似乎都是用 r−l 作为代价的 但是疑似如果令 f(x) 为至少选 x 段 ≥s 的此时最多能划分的段数 这个好像也是凸的
但是我在实现的时候 样例 4 没过 把二分答案的上界调成 k 就过了 这有道理吗????
#include <bits/stdc++.h>
#define PR(x) printf(x ? "YES\n" : "NO\n")
#define pr(x) printf(x ? "Yes\n" : "No\n")
#define mk make_pair
#define pb emplace_back
#define fi first
#define se second
#define pii pair<int, int>
#define fore(i, u, v) for (int i = h[u], v = e[i].v; i; v = e[i = e[i].nxt].v)
#define all(x) x.begin(), x.end()
#define int long long
using namespace std;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (! isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}
const int maxn = 2.5e5 + 10;
int n, k, s, a[maxn];
pii f[maxn];
void work(int p) {
int l = 1;
for (int i = 1; i <= n; i ++) {
f[i] = {f[i - 1].fi + 1, f[i - 1].se};
while (a[i] - a[l] >= s) l ++;
if (a[i] - a[l - 1] >= s)
f[i] = max(f[i], {f[l - 1].fi + 1 - p, f[l - 1].se + 1});
}
}
int chk(int p) {
int l = -n, r = 0, ans = 0;
while (l < r) {
int mi = (l + r + 1) >> 1; work(mi);
if (f[n].se >= p) ans = f[n].fi + mi * p, l = mi;
else r = mi - 1;
}
return ans;
}
signed main() {
n = read(), k = read(), s = read();
for (int i = 1; i <= n; i ++) a[i] = read() + a[i - 1];
int l = 0, r = k;
// 这里 r 改了,原来是 n
while (l + 1 < r) {
int mi = l + r >> 1;
if (chk(mi) >= k) l = mi; else r = mi;
}
if (chk(r) >= k) cout << r; else cout << l;
return 0;
}