Problem p01544 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <vector>

using namespace std;

const long long inf = 1e13;

struct RMQ {
  int N;
  long long dat[8192];
  void init(int N_) {
    N = 1;
    while (N < N_)
      N *= 2;
    for (int i = 1; i <= N * 2 - 1; i++)
      dat[i] = -inf;
  }
  void update(int i, long long x) {
    i += N;
    while (i > 0) {
      dat[i] = max(dat[i], x);
      i /= 2;
    }
  }
  long long get(int i) { //[0,i)
    if (i == 0)
      return -inf;
    int le = 0, ri = N;
    int k = 1;
    long long res = -inf;
    while (ri - le > 1) {
      int mid = (le + ri) / 2;
      if (mid <= i) {
        res = max(res, dat[k * 2]);
        k = k * 2 + 1;
        le = mid;
      } else {
        k = k * 2;
        ri = mid;
      }
    }
    if (ri == i)
      res = max(res, dat[k]);
    return res;
  }
};

RMQ rmq;

long long sum[4040];
long long dp[4040][4040];

vector<long long> vals;

int N;
long long a[4040];

vector<int> C;

int main() {
  scanf("%lld", &N);
  for (int i = 0; i < N; i++)
    scanf("%lld", a + i);
  sum[0] = a[0];
  for (int i = 1; i < N; i++)
    sum[i] = sum[i - 1] + a[i];
  for (int i = 0; i < 4040; i++)
    for (int j = 0; j < 4040; j++) {
      dp[i][j] = inf;
    }
  for (int i = 0; i < N; i++)
    dp[i][1] = sum[i];
  for (int k = 2; k <= N; k++) {
    vals.clear();
    for (int i = 0; i < N; i++) {
      if (dp[i][k - 1] < inf)
        vals.push_back(dp[i][k - 1] + sum[i]);
    }
    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    rmq.init(vals.size());
    for (int j = 0; j < N; j++) {
      int id =
          distance(vals.begin(), lower_bound(vals.begin(), vals.end(), sum[j]));
      long long ma = rmq.get(id);
      if (ma > -inf) {
        dp[j][k] = min(dp[j][k], sum[j] - ma);
      }
      id = distance(vals.begin(), lower_bound(vals.begin(), vals.end(),
                                              dp[j][k - 1] + sum[j]));
      rmq.update(id, sum[j]);
    }
  }
  int ans = 0;
  for (int i = 1; i <= N; i++) {
    if (dp[N - 1][i] < inf) {
      ans = i;
    }
  }
  printf("%d\n", ans);
  int cur = N - 1;
  for (int i = ans; i >= 2; i--) {
    bool flg = false;
    for (int j = cur - 1; j >= 0; j--) {
      if (dp[j][i - 1] < sum[cur] - sum[j] && sum[cur] - sum[j] == dp[cur][i]) {
        C.push_back(j + 1);
        cur = j;
        flg = true;
        break;
      }
    }
    assert(flg);
  }
  reverse(C.begin(), C.end());
  for (int i = 0; i < C.size(); i++)
    printf("%d%c", C[i], i == C.size() - 1 ? '\n' : ' ');
  if (C.size() == 0)
    printf("\n");
  //	assert(C.size()>=ans-1);
  /*	long long prev=-inf;
          for(int i=0;i<(int)C.size();i++){
                  int le=i==0?0:C[i-1];
                  //int ri=i==C.size()-1?N-1:C[i+1]-1;
                  int ri=C[i];
                  long long sum=0;
                  for(int j=le;j<ri;j++) sum+=a[j];
          //	assert(prev<sum);
                  prev=sum;
          }
          long long xx=0;
          if(C.size()>0){
                  for(int i=C[C.size()-1];i<N;i++) xx+=a[i];
          //	assert(prev<xx);
          }*/
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <vector>

using namespace std;

const long long inf = 1e13;

struct RMQ {
  int N;
  long long dat[8192];
  void init(int N_) {
    N = 1;
    while (N < N_)
      N *= 2;
    for (int i = 1; i <= N * 2 - 1; i++)
      dat[i] = -inf;
  }
  void update(int i, long long x) {
    i += N;
    while (i > 0) {
      dat[i] = max(dat[i], x);
      i /= 2;
    }
  }
  long long get(int i) { //[0,i)
    if (i == 0)
      return -inf;
    int le = 0, ri = N;
    int k = 1;
    long long res = -inf;
    while (ri - le > 1) {
      int mid = (le + ri) / 2;
      if (mid <= i) {
        res = max(res, dat[k * 2]);
        k = k * 2 + 1;
        le = mid;
      } else {
        k = k * 2;
        ri = mid;
      }
    }
    if (ri == i)
      res = max(res, dat[k]);
    return res;
  }
};

RMQ rmq;

long long sum[4040];
long long dp[4040][4040];

vector<long long> vals;

int N;
long long a[4040];

vector<int> C;

int main() {
  scanf("%lld", &N);
  for (int i = 0; i < N; i++)
    scanf("%lld", a + i);
  sum[0] = a[0];
  for (int i = 1; i < N; i++)
    sum[i] = sum[i - 1] + a[i];
  for (int i = 0; i < 4040; i++)
    for (int j = 0; j < 4040; j++) {
      dp[i][j] = inf;
    }
  for (int i = 0; i < N; i++)
    dp[i][1] = sum[i];
  for (int k = 2; k <= N; k++) {
    vals.clear();
    for (int i = 0; i < N; i++) {
      if (dp[i][k - 1] < inf)
        vals.push_back(dp[i][k - 1] + sum[i]);
    }
    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    rmq.init(vals.size());
    for (int j = 0; j < N; j++) {
      int id =
          distance(vals.begin(), lower_bound(vals.begin(), vals.end(), sum[j]));
      long long ma = rmq.get(id);
      if (ma > -inf) {
        dp[j][k] = min(dp[j][k], sum[j] - ma);
      }
      if (dp[j][k - 1] < inf) {
        id = distance(vals.begin(), lower_bound(vals.begin(), vals.end(),
                                                dp[j][k - 1] + sum[j]));
        rmq.update(id, sum[j]);
      }
    }
  }
  int ans = 0;
  for (int i = 1; i <= N; i++) {
    if (dp[N - 1][i] < inf) {
      ans = i;
    }
  }
  printf("%d\n", ans);
  int cur = N - 1;
  for (int i = ans; i >= 2; i--) {
    bool flg = false;
    for (int j = cur - 1; j >= 0; j--) {
      if (dp[j][i - 1] < sum[cur] - sum[j] && sum[cur] - sum[j] == dp[cur][i]) {
        C.push_back(j + 1);
        cur = j;
        flg = true;
        break;
      }
    }
    assert(flg);
  }
  reverse(C.begin(), C.end());
  for (int i = 0; i < C.size(); i++)
    printf("%d%c", C[i], i == C.size() - 1 ? '\n' : ' ');
  if (C.size() == 0)
    printf("\n");
  //	assert(C.size()>=ans-1);
  /*	long long prev=-inf;
          for(int i=0;i<(int)C.size();i++){
                  int le=i==0?0:C[i-1];
                  //int ri=i==C.size()-1?N-1:C[i+1]-1;
                  int ri=C[i];
                  long long sum=0;
                  for(int j=le;j<ri;j++) sum+=a[j];
          //	assert(prev<sum);
                  prev=sum;
          }
          long long xx=0;
          if(C.size()>0){
                  for(int i=C[C.size()-1];i<N;i++) xx+=a[i];
          //	assert(prev<xx);
          }*/
  return 0;
}