Problem p01544 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i <= (n); ++i)
#define all(c) (c).begin(), (c).end()
#define fs first
#define sc second
#define pb push_back
#define show(x) cout << #x << " " << x << endl
typedef long long ll;
int N;
ll a[4000], sum[4001];
short int inf = 10000, p2[4001];
vector<short int> seg[4001];
short int pl[4001][8191];
vector<ll> vals[4001];
int query(int a, int b, int l, int r, int k, int id) {
  if (b <= l || r <= a)
    return -inf;
  if (a <= l && r <= b)
    return seg[id][k];
  return max(query(a, b, l, (l + r) / 2, 2 * k + 1, id),
             query(a, b, (l + r) / 2, r, 2 * k + 2, id));
}
int main() {
  cin >> N;
  rep(i, N) cin >> a[i];
  rep(i, N + 1) {
    p2[i] = 1;
    while (p2[i] <= i)
      p2[i] *= 2;
  }
  rep(i, N + 1) seg[i].resize(p2[i] * 2);
  rep(i, N) sum[i + 1] = sum[i] + a[i];
  rep(l, N) {
    for (int r = l + 1; r <= N; r++) {
      vals[r].pb(sum[r] - sum[l]);
    }
  }
  rep1(r, N) {
    sort(all(vals[r]));
    vals[r].erase(unique(all(vals[r])), vals[r].end());
  }
  for (int l = 0; l < N; l++) {
    for (int r = l + 1; r <= N; r++) {
      //			printf("(l,r)=%d,%d\\n",l,r);
      ll s = sum[r] - sum[l];
      int id = lower_bound(all(vals[l]), s) - vals[l].begin();
      int v = query(0, id, 0, p2[l], 0, l);
      if (l == 0)
        v = 0;
      if (l == 0 || v >= 1) {
        int id2 = lower_bound(all(vals[r]), s) - vals[r].begin();
        if (v + 1 > seg[r][p2[r] - 1 + id2]) {
          seg[r][p2[r] - 1 + id2] = v + 1;
          pl[r][p2[r] - 1 + id2] = l;
          // printf("seg[%d][%d]=%d\\n",r,p2-1+id2,seg[r][p2-1+id2]);
          int p = (p2[r] - 1 + id2 - 1) / 2;
          while (true) {
            if (seg[r][p * 2 + 1] > seg[r][p * 2 + 2]) {
              seg[r][p] = seg[r][p * 2 + 1], pl[r][p] = pl[r][p * 2 + 1];
            } else {
              seg[r][p] = seg[r][p * 2 + 2], pl[r][p] = pl[r][p * 2 + 2];
            }
            if (p == 0)
              break;
            p = (p - 1) / 2;
          }
        }
      }
    }
  }
  cout << seg[N][0] << endl;
  vector<int> ans;
  int now = N;
  while (true) {
    now = pl[now][0];
    if (now == 0)
      break;
    ans.pb(now);
  }
  sort(all(ans));
  rep(i, ans.size()) {
    if (i == ans.size() - 1)
      cout << ans[i] << endl;
    else
      cout << ans[i] << " ";
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i <= (n); ++i)
#define all(c) (c).begin(), (c).end()
#define fs first
#define sc second
#define pb push_back
#define show(x) cout << #x << " " << x << endl
typedef long long ll;
int N;
ll a[4000], sum[4001];
short int seg[4001][8191], p2 = 4096, inf = 10000;
short int pl[4001][8191];
vector<ll> vals[4001];
int query(int a, int b, int l, int r, int k, int id) {
  if (b <= l || r <= a)
    return -inf;
  if (a <= l && r <= b)
    return seg[id][k];
  return max(query(a, b, l, (l + r) / 2, 2 * k + 1, id),
             query(a, b, (l + r) / 2, r, 2 * k + 2, id));
}
int main() {
  cin >> N;
  rep(i, N) cin >> a[i];
  rep(i, N) sum[i + 1] = sum[i] + a[i];
  rep(l, N) {
    for (int r = l + 1; r <= N; r++) {
      vals[r].pb(sum[r] - sum[l]);
    }
  }
  rep1(r, N) {
    sort(all(vals[r]));
    vals[r].erase(unique(all(vals[r])), vals[r].end());
  }
  rep(j, 8191) seg[0][j] = 1;
  for (int l = 0; l < N; l++) {
    for (int r = l + 1; r <= N; r++) {
      //			printf("(l,r)=%d,%d\\n",l,r);
      ll s = sum[r] - sum[l];
      int id = lower_bound(all(vals[l]), s) - vals[l].begin();
      int v = query(0, id, 0, p2, 0, l);
      if (l == 0)
        v = 0;
      if (l == 0 || v >= 1) {
        int id2 = lower_bound(all(vals[r]), s) - vals[r].begin();
        if (v + 1 > seg[r][p2 - 1 + id2]) {
          seg[r][p2 - 1 + id2] = v + 1;
          pl[r][p2 - 1 + id2] = l;
          // printf("seg[%d][%d]=%d\\n",r,p2-1+id2,seg[r][p2-1+id2]);
          int p = (p2 - 1 + id2 - 1) / 2;
          while (true) {
            if (seg[r][p * 2 + 1] > seg[r][p * 2 + 2]) {
              seg[r][p] = seg[r][p * 2 + 1], pl[r][p] = pl[r][p * 2 + 1];
            } else {
              seg[r][p] = seg[r][p * 2 + 2], pl[r][p] = pl[r][p * 2 + 2];
            }
            if (p == 0)
              break;
            p = (p - 1) / 2;
          }
        }
      }
    }
  }
  cout << seg[N][0] << endl;
  vector<int> ans;
  int now = N;
  while (true) {
    now = pl[now][0];
    if (now == 0)
      break;
    ans.pb(now);
  }
  sort(all(ans));
  rep(i, ans.size()) {
    if (i == ans.size() - 1)
      cout << ans[i] << endl;
    else
      cout << ans[i] << " ";
  }
}