社区讨论

关于这题的的另一个切入

AT_arc168_e [ARC168E] Subsegments with Large Sums参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@m5fdnw6x
此快照首次捕获于
2025/01/02 21:44
去年
此快照最后确认于
2025/11/04 12:03
4 个月前
查看原帖
题解里我看似乎都是用 rlr-l 作为代价的 但是疑似如果令 f(x)f(x) 为至少选 xxs\ge s 的此时最多能划分的段数 这个好像也是凸的
但是我在实现的时候 样例 4 没过 把二分答案的上界调成 kk 就过了 这有道理吗????
CPP
#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;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...