Problem p00912 (C++) — buggy submission, verdict: Time Limit Exceeded

#define N (1 << 16)
#include <bits/stdc++.h>
using namespace std;

int dp[N];
int w, n, x, sum[N];

bool solve(int x) {
  memset(dp, 0, sizeof(dp));
  dp[0] = 0, dp[1] = 1;

  for (int i = 1, j = 0, k = 0; i < n; i++) {
    for (; w - (sum[i] - sum[j]) < i - j - 1; j++)
      ;
    for (int u = 0, v = 0; u = w - (sum[i] - sum[k]), v = i - k - 1,
             v ? u / v + !!(u % v) <= x : !u;
         k++)
      ;
    dp[i + 1] = dp[i] + (dp[k] - dp[j] > 0);
  }

  for (int i = n - 1; i >= 0; i--) {
    if (w - (sum[n] - sum[i]) < n - i - 1)
      return 0;
    if (dp[i + 1] - dp[i])
      return 1;
  }
  return 0;
}

int main() {
  for (; cin >> w >> n, w;) {
    for (int i = 1; i <= n; i++)
      scanf("%d", &x), sum[i] = sum[i - 1] + x;
    int Left = 1, Right = w - 1;
    for (; Left < Right;) {
      int mid = (Left + Right) >> 1;
      if (solve(mid))
        Right = mid;
      else
        Left = mid + 1;
    }
    cout << Left << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, w, len[51111], psum[51111];
struct SegTree {
  int n, seg[401111];
  void init(int _n) {
    n = _n;
    fill(seg, seg + 8 * n, 0);
  }
  void set(int i, int x) {
    // printf("[%d] = %d\\n",i,x);
    set(i, x, 0, n, 0);
  }
  int qmax(int l, int r) {
    // printf("%d - %d:  %d\\n",l,r,qmax(l,r,0,n,0));
    return qmax(l, r, 0, n, 0);
  }
  void set(int i, int x, int sl, int sr, int sid) {
    if (sr <= i || i < sl)
      return;
    if (sr - sl <= 1) {
      seg[sid] = x;
      return;
    }
    set(i, x, sl, (sl + sr) / 2, sid * 2 + 1);
    set(i, x, (sl + sr) / 2, sr, sid * 2 + 2);
    seg[sid] = max(seg[sid * 2 + 1], seg[sid * 2 + 2]);
  }
  int qmax(int l, int r, int sl, int sr, int sid) {
    if (sr <= l || r <= sl)
      return 0;
    if (l <= sl && sr <= r)
      return seg[sid];
    return max(qmax(l, r, sl, (sl + sr) / 2, sid * 2 + 1),
               qmax(l, r, (sl + sr) / 2, sr, sid * 2 + 2));
  }
} st;
int ceiling(int x, int y) {
  if (y == 0) {
    printf("QQ %d %d\\n", x, y);
    // while(1);
  }
  return (x - 1) / y + 1;
}
bool check(int d) {
  // printf("\\t\\t\\td = %d\\n",d);
  static int dp[51111];
  // memset(dp,0,sizeof(dp));
  fill(dp, dp + n, 0);
  st.init(n);

  for (int i = 1; i < n; i++) {
    // printf(" i= %d\\n",i);
    int lb = -1, ub = i - 1, b, a;
    while (1 < ub - lb) {
      int md = (lb + ub) / 2;
      if (ceiling(w - psum[i + 1] + psum[md + 1], i - md - 1) <= d)
        lb = md;
      else
        ub = md;
    }
    b = lb;
    lb = -1, ub = i;
    while (1 < ub - lb) {
      int md = (lb + ub) / 2;
      if (psum[i + 1] - psum[md + 1] + i - md - 1 <= w)
        ub = md;
      else
        lb = md;
    }
    a = ub;
    // printf("%d - %d\\n",a,b);
    if (psum[i + 1] + i <= w && ceiling(w - psum[i + 1], i) <= d)
      dp[i] = 1;
    // printf("%d<=%d && %d/%d<=%d\\n", psum[i+1]+i,w, w-psum[i+1], i, d);
    if (a <= b)
      dp[i] = st.qmax(a, b + 1);
    st.set(i, dp[i]);
    // printf("dp(%d) = %d\\n",i,dp[i]);
  }
  int res = 0;
  for (int i = 0; i < n - 1; i++) {
    if (psum[n] - psum[i + 1] + n - i - 1 <= w)
      res = max(res, dp[i]);
  }

  return res || dp[n - 1] || psum[n] + n - 1 <= w;
}
int main() {
  while (scanf("%d%d", &w, &n) && (n + w > 0)) {
    for (int i = 0; i < n; i++)
      scanf("%d", &len[i]);
    psum[0] = 0;
    for (int i = 0; i < n; i++)
      psum[i + 1] = psum[i] + len[i];
    int lb = 0, ub = w;
    while (1 < ub - lb) {
      int md = (lb + ub) / 2;
      if (check(md))
        ub = md;
      else
        lb = md;
    }
    printf("%d\\n", ub);
  }
}

/*

11 4
4 2 1 3
5 7
1 1 1 2 2 1 2
11 7
3 1 3 1 3 3 4
100 3
30 30 39
30 3
2 5 3
0 0

*/