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

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)

using namespace std;

inline int f(int n, int i, int L, const vector<int> &sum_rev) {
  return (sum_rev[i - n] - sum_rev[i]) + L * (n - 1);
}

int dp[50010];
int sum_dp[50010];

int main() {
  int W, N;
  while (cin >> W >> N && N) {
    vector<int> x(N);
    REP(i, N) cin >> x[i];

    vector<int> sum_rev(N + 1);
    sum_rev[N] = 0;
    for (int i = N - 1; i >= 0; i--) {
      sum_rev[i] = sum_rev[i + 1] + x[i];
    }

    int lb_L = 0, ub_L = W; // ub
    while (ub_L - lb_L > 1) {
      int L = (lb_L + ub_L) / 2;
      dp[0] = 1;
      dp[1] = 0;
      sum_dp[1] = 1;
      sum_dp[2] = 1;

      for (int i = 2; i < N; i++) {
        dp[i] = 0;
        sum_dp[i] = sum_dp[i - 1] + dp[i - 1];

        int lb = 1, ub = min(i, (W + L) / (L + 1) + 2); // ub  true ??
        while (ub - lb > 1) {
          int n = (ub + lb) / 2;
          if (f(n, i, L, sum_rev) >= W) {
            ub = n;
          } else {
            lb = n;
          }
        }
        int begin_n = ub;

        // printf("dp[%d] : begin %d \\n", i, begin_n);
        if (f(begin_n, i, L, sum_rev) < W) {
          continue;
        }

        lb = begin_n, ub = i + 1; // lb
        while (ub - lb > 1) {
          int n = (ub + lb) / 2;
          if (f(n, i, 1, sum_rev) <= W) {
            lb = n;
          } else {
            ub = n;
          }
        }
        int end_n = lb;

        // printf("dp[%d] : end %d \\n", i, end_n);
        if (f(end_n, i, 1, sum_rev) > W) {
          continue;
        }

        int begin = i - end_n;
        int end = i - begin_n;
        // [begin, end]
        if (sum_dp[end + 1] - sum_dp[begin] > 0) {
          dp[i] = 1;
        }
        // printf("dp[%d] : [dp[%d], dp[%d]] (%d) -> %d\\n", i, begin, end,
        // sum_dp[end + 1] - sum_dp[begin], dp[i]);
      }

      bool ok = false;
      for (int n = 1; n <= N && (n - 1) + sum_rev[N - n] <= W; n++) {
        // printf("n - 1 + sum_rev[%d] = %d\\n", i, n - 1 + sum_rev[i]);
        if (dp[N - n]) {
          ok = true;
          break;
        }
      }
      // printf("L %d  is %d\\n", L, ok);

      if (ok) {
        ub_L = L;
      } else {
        lb_L = L;
      }
    }

    cout << ub_L << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)

using namespace std;

inline int f(int n, int i, int L, const vector<int> &sum_rev) {
  return (sum_rev[i - n] - sum_rev[i]) + L * (n - 1);
}

int dp[50010];
int sum_dp[50010];

int main() {
  int W, N;
  while (cin >> W >> N && N) {
    vector<int> x(N);
    REP(i, N) cin >> x[i];

    vector<int> sum_rev(N + 1);
    sum_rev[N] = 0;
    for (int i = N - 1; i >= 0; i--) {
      sum_rev[i] = sum_rev[i + 1] + x[i];
    }

    int lb_L = 0, ub_L = W; // ub
    while (ub_L - lb_L > 1) {
      int L = (lb_L + ub_L) / 2;
      dp[0] = 1;
      dp[1] = 0;
      sum_dp[1] = 1;
      sum_dp[2] = 1;

      for (int i = 2; i < N; i++) {
        dp[i] = 0;
        sum_dp[i] = sum_dp[i - 1] + dp[i - 1];

        int lb = 1, ub = i; // ub
        while (ub - lb > 1) {
          int n = (ub + lb) / 2;
          if (f(n, i, L, sum_rev) >= W) {
            ub = n;
          } else {
            lb = n;
          }
        }
        int begin_n = ub;

        // printf("dp[%d] : begin %d \\n", i, begin_n);
        if (f(begin_n, i, L, sum_rev) < W) {
          continue;
        }

        lb = begin_n, ub = i + 1; // lb
        while (ub - lb > 1) {
          int n = (ub + lb) / 2;
          if (f(n, i, 1, sum_rev) <= W) {
            lb = n;
          } else {
            ub = n;
          }
        }
        int end_n = lb;

        // printf("dp[%d] : end %d \\n", i, end_n);
        if (f(end_n, i, 1, sum_rev) > W) {
          continue;
        }

        int begin = i - end_n;
        int end = i - begin_n;
        // [begin, end]
        if (sum_dp[end + 1] - sum_dp[begin] > 0) {
          dp[i] = 1;
        }
        // printf("dp[%d] : [dp[%d], dp[%d]] (%d) -> %d\\n", i, begin, end,
        // sum_dp[end + 1] - sum_dp[begin], dp[i]);
      }

      bool ok = false;
      for (int n = 1; n <= N && (n - 1) + sum_rev[N - n] <= W; n++) {
        // printf("n - 1 + sum_rev[%d] = %d\\n", i, n - 1 + sum_rev[i]);
        if (dp[N - n]) {
          ok = true;
          break;
        }
      }
      // printf("L %d  is %d\\n", L, ok);

      if (ok) {
        ub_L = L;
      } else {
        lb_L = L;
      }
    }

    cout << ub_L << endl;
  }
  return 0;
}