Problem p02581 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
using namespace std;

const int MAX = 6005;
const int INF = 1e9;
int dp[MAX][MAX];  // best with i, j in knapsack
int nxt[MAX][MAX]; // next location that has max
int label[MAX];    // stores which group
vector<int> a;
vector<int> groups[MAX];
int id[MAX]; // stores which idx in loc
int n;
int ans = 0;
vector<int> loc[MAX]; // stores loc
void update(int x, int y, int val) {
  if (x > y)
    swap(x, y);
  assert(x < y);
  dp[x][y] = max(dp[x][y], val);
}
int check(int u, int v, int w) { return (a[u] == a[v] && a[v] == a[w]); }
void process(int u, int v, int w, int x, int y) {
  // fun fun fun
  assert(u < v);
  assert(dp[u][v] != -1);
  update(u, w, dp[u][v] + check(v, x, y));
  update(u, x, dp[u][v] + check(v, w, y));
  update(u, y, dp[u][v] + check(v, x, w));
  update(v, w, dp[u][v] + check(u, x, y));
  update(v, x, dp[u][v] + check(u, w, y));
  update(v, y, dp[u][v] + check(u, w, x));
  update(w, x, dp[u][v] + check(u, v, y));
  update(w, y, dp[u][v] + check(u, v, x));
  update(x, y, dp[u][v] + check(u, v, w));
}
void go(int x, int y) {
  assert(x < y);
  if (label[y] == n - 1) {
    ans = max(ans, dp[x][y] + check(x, y, 3 * n - 1));
    return;
  }
  int cur_x = nxt[a[x]][label[y] + 1];
  int cur_y = nxt[a[y]][label[y] + 1];
  int group;
  if (cur_x != -1 && cur_y != -1) {
    group = min(label[cur_x], label[cur_y]);
    if (group == n) {
      ans = max(ans, dp[x][y] + check(x, y, 3 * n - 1));
    } else {
      process(x, y, groups[group][0], groups[group][1], groups[group][2]);
    }
  }
  group = label[y] + 1;
  process(x, y, groups[group][0], groups[group][1], groups[group][2]);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n;
  vector<int> tmp(3 * n);
  for (int i = 0; i < 3 * n; i++)
    cin >> tmp[i];
  int add = 0;
  int _n = n;
  a.push_back(tmp[0]);
  a.push_back(tmp[1]);
  for (int i = 2; i < 3 * n - 1; i += 3) {
    if (tmp[i] == tmp[i + 1] && tmp[i + 1] == tmp[i + 2]) {
      _n--;
      add++;
    } else {
      a.push_back(tmp[i]);
      a.push_back(tmp[i + 1]);
      a.push_back(tmp[i + 2]);
    }
  }
  a.push_back(tmp.back());
  n = _n;
  if (n == 0) {
    cout << 0 + add << '\\n';
    return 0;
  } else if (n == 1) {
    if (a[0] == a[1] && a[1] == a[2]) {
      cout << 1 + add << '\\n';
    } else {
      cout << 0 + add << '\\n';
    }
    return 0;
  }
  label[0] = label[1] = 0;
  for (int i = 2; i < 3 * n; i++) {
    label[i] = (i + 1) / 3;
    groups[label[i]].push_back(i);
  }
  for (int i = 0; i < 3 * n; i++) {
    id[i] = (int)loc[a[i]].size();
    loc[a[i]].push_back(i);
  }
  for (int i = 0; i < 3 * n; i++) {
    for (int j = 0; j < 3 * n; j++) {
      dp[i][j] = -1;
    }
  }
  for (int i = 0; i < MAX; i++) {
    for (int j = 0; j < MAX; j++) {
      nxt[i][j] = -1;
    }
  }
  for (int i = 1; i <= n; i++) {
    if ((int)loc[i].size() == 0)
      continue;
    for (int j : loc[i]) {
      int cur = label[j];
      while (cur != -1 && nxt[i][cur] == -1) {
        nxt[i][cur] = j;
        cur--;
      }
    }
  }
  dp[0][1] = 0;
  for (int i = 1; i < 3 * n; i++) {
    for (int j = 0; j < i; j++) {
      if (dp[j][i] != -1) {
        go(j, i);
      }
    }
  }
  cout << ans + add << '\\n';
  return 0;
}


Error: -11

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

const int MAX = 6005;
const int INF = 1e9;
int dp[MAX][MAX]; // best with i, j in knapsack
int nxt[MAX];     // next location that has max
int label[MAX];   // stores which group
vector<int> a;
vector<int> groups[MAX];
int id[MAX]; // stores which idx in loc
int n;
int ans = 0;
vector<int> loc[MAX]; // stores loc
void update(int x, int y, int val) {
  if (x > y)
    swap(x, y);
  assert(x < y);
  dp[x][y] = max(dp[x][y], val);
}
int check(int u, int v, int w) { return (a[u] == a[v] && a[v] == a[w]); }
void process(int u, int v, int w, int x, int y) {
  // fun fun fun
  assert(u < v);
  update(u, w, dp[u][v] + check(v, x, y));
  update(u, x, dp[u][v] + check(v, w, y));
  update(u, y, dp[u][v] + check(v, x, w));
  update(v, w, dp[u][v] + check(u, x, y));
  update(v, x, dp[u][v] + check(u, x, y));
  update(v, y, dp[u][v] + check(u, w, x));
  update(w, x, dp[u][v] + check(u, v, y));
  update(w, y, dp[u][v] + check(u, v, x));
  update(x, y, dp[u][v] + check(u, v, w));
}
int occur(int i) {
  if (id[i] == (int)loc[a[i]].size() - 1) {
    return -1;
  } else {
    return loc[a[i]][id[i] + 1];
  }
}
void go(int x, int y) {
  assert(x < y);
  //    cout << x << " WORKING " << y  << '\\n';
  //    cout << label[y] << " LABEL" << '\\n';
  if (label[y] == n - 1) {
    // you're done already
    //        cout << "FINISH" << '\\n';
    ans = max(ans, dp[x][y] + check(x, y, 3 * n - 1));
    return;
  }
  // case 1, you just move on until next instance of the same thing
  // since otherwise you would swap, there's no reason not to swap
  int rep = 0;
  int cur_x = nxt[x];
  int cur_y = nxt[y];
  while (min(label[cur_x], label[cur_y]) == label[y]) {
    if (label[cur_x] < label[cur_y]) {
      if (occur(cur_x) == -1) {
        rep = -1;
        break;
      }
      cur_x = occur(cur_x);
    } else if (label[cur_x] > label[cur_y]) {
      if (occur(cur_y) == -1) {
        rep = -1;
        break;
      }
      cur_y = occur(cur_y);
    } else {
      if (occur(cur_x) == -1 || occur(cur_y) == -1) {
        rep = -1;
        break;
      }
      cur_x = occur(cur_x);
      cur_y = occur(cur_y);
    }
  }
  int group;
  if (rep == 0)
    rep = min(label[cur_x], label[cur_y]);
  assert(rep != label[y]);
  if (rep != -1) {
    group = rep;
    if (group == n) {
      ans = max(ans, dp[x][y] + check(x, y, 3 * n - 1));
    } else {
      //            cout << x << " " << y << " " << groups[group][0] << " " <<
      //            groups[group][1] << " " << groups[group][2] << '\\n';
      process(x, y, groups[group][0], groups[group][1], groups[group][2]);
    }
    //        cout << group << " " << (groups[group]).size() << " HUH" << '\\n';

    if (rep == label[y] + 1)
      return;
  }
  //    cout << "YES" << '\\n';
  // gotta change at least 1
  group = label[y] + 1;
  process(x, y, groups[group][0], groups[group][1], groups[group][2]);
}
int main() {
  //    ios_base::sync_with_stdio(0); cin.tie(0);
  cin >> n;
  vector<int> tmp(3 * n);
  for (int i = 0; i < 3 * n; i++)
    cin >> tmp[i];
  int add = 0;
  int _n = n;
  a.push_back(tmp[0]);
  a.push_back(tmp[1]);
  for (int i = 2; i < 3 * n - 1; i += 3) {
    if (tmp[i] == tmp[i + 1] && tmp[i + 1] == tmp[i + 2]) {
      _n--;
      add++;
    } else {
      a.push_back(tmp[i]);
      a.push_back(tmp[i + 1]);
      a.push_back(tmp[i + 2]);
    }
  }
  a.push_back(tmp.back());
  n = _n;
  if (n == 0) {
    cout << 0 + add << '\\n';
    return 0;
  } else if (n == 1) {
    if (a[0] == a[1] && a[1] == a[2]) {
      cout << 1 + add << '\\n';
    } else {
      cout << 0 + add << '\\n';
    }
    return 0;
  }
  label[0] = label[1] = 0;
  for (int i = 2; i < 3 * n; i++) {
    label[i] = (i + 1) / 3;
    groups[label[i]].push_back(i);
  }
  for (int i = 0; i < 3 * n; i++) {
    id[i] = (int)loc[a[i]].size();
    loc[a[i]].push_back(i);
  }
  for (int i = 0; i < 3 * n; i++) {
    for (int j = 0; j < 3 * n; j++) {
      dp[i][j] = -1;
    }
  }
  dp[0][1] = 0;
  for (int i = 0; i < 3 * n; i++) {
    if (id[i] == (int)loc[a[i]].size() - 1) {
      nxt[i] = INF;
    } else {
      nxt[i] = loc[a[i]][id[i] + 1];
      while (label[i] == label[nxt[i]]) {
        if (id[nxt[i]] == (int)loc[a[i]].size() - 1) {
          nxt[i] = INF;
          break;
        }
        nxt[i] = loc[a[i]][id[nxt[i]] + 1];
      }
    }
  }
  for (int i = 1; i < 3 * n; i++) {
    for (int j = 0; j < i; j++) {
      if (dp[j][i] != -1) {
        //                cout << j << " " << i << '\\n';
        go(j, i);
      }
    }
  }
  cout << ans + add << '\\n';
  return 0;
}