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

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
using namespace std;
typedef long long LL;

vector<int> lc;
vector<int> rc;
void skip(const string &s, int &k, char c) {
  if (k >= s.size()) {
    // cerr << "index " << k << " but s.size() = " << s.size() << endl;
    assert(false);
  }
  if (s[k] != c) {
    // cerr << "assert " << c << " but " << s[k] << endl;
    assert(false);
  }
  k++;
}
pair<int, int> parse(const string &s, int k) {
  if (s[k] == '(') {
    int v = lc.size();
    lc.push_back(-1);
    rc.push_back(-1);

    auto lcp = parse(s, k + 1);
    k = lcp.first;
    skip(s, k, ' ');
    auto rcp = parse(s, k);
    k = rcp.first;
    skip(s, k, ')');

    lc[v] = lcp.second;
    rc[v] = rcp.second;

    return make_pair(k, v);
  } else if (s[k] == 'x') {
    int v = lc.size();
    lc.push_back(-1);
    rc.push_back(-1);
    return make_pair(k + 1, v);
  } else {
    // cerr << "s[" << k << "] = " << s[k] << endl;
    assert(false);
  }
}

int called[200][200] = {};
bool memo[200][200] = {};
bool check(int u, int v) {
  if (u == v)
    return true;
  if (u == -1 || v == -1)
    return false;

  if (u > v)
    swap(u, v);

  assert(called[u][v] != 1);
  if (called[u][v] != 0)
    return memo[u][v];
  called[u][v] = 1;

  memo[u][v] = false;

  if (check(lc[u], lc[v]) && check(rc[u], rc[v])) {
    memo[u][v] = true;
    goto RET;
  }

  if (check(lc[u], rc[v]) && check(rc[u], lc[v])) {
    memo[u][v] = true;
    goto RET;
  }

RET:
  called[u][v] = 2;
  return memo[u][v];
}

vector<vector<int>> roots;
void calc_roots(int u) {
  if (u == -1)
    return;
  roots[u].push_back(u);
  if (lc[u] == -1)
    return;
  calc_roots(lc[u]);
  calc_roots(rc[u]);
  roots[u].insert(roots[u].end(), roots[lc[u]].begin(), roots[lc[u]].end());
  roots[u].insert(roots[u].end(), roots[rc[u]].begin(), roots[rc[u]].end());
  vector<int> nr;

  for (int a : roots[u]) {
    bool ok = true;
    for (int b : nr) {
      if (check(a, b)) {
        ok = false;
      }
    }
    if (ok)
      nr.push_back(a);
  }
  roots[u].swap(nr);
}

typedef long long LL;
pair<LL, LL> memo_s[200];
pair<LL, LL> calc_sims(int r) {
  if (memo_s[r].second != 0)
    return memo_s[r];
  int u = lc[r], v = rc[r];
  if (u == -1) {
    assert(v == -1);
    return make_pair(0LL, 1LL);
  }
  assert(v != -1);

  int all = roots[u].size() + roots[v].size();
  int same = 0;
  for (int a : roots[u]) {
    int same_cnt = 0;
    for (int b : roots[v]) {
      if (check(a, b)) {
        same_cnt++;
        same++;
      }
    }
    assert(same_cnt <= 1);
  }
  int type = all - same;
  return memo_s[r] = pair<LL, LL>(same, type);
}

// u < v (sims)
bool comp(pair<LL, LL> a, pair<LL, LL> b) {
  return a.first * b.second < a.second * b.first;
}
bool eq(pair<LL, LL> a, pair<LL, LL> b) { return !comp(a, b) && !comp(b, a); }

int memo_c[200][200];
bool comp(int u, int v) {
  if (memo_c[u][v] != -1) {
    return memo_c[u][v];
  }
  auto a = calc_sims(u);
  auto b = calc_sims(v);
  if (comp(a, b))
    return memo_c[u][v] = true;
  if (comp(b, a))
    return memo_c[u][v] = false;
  if (lc[u] == -1) {
    assert(lc[v] == -1);
    return memo_c[u][v] = false;
  }

  int c1 = lc[u], c2 = rc[u];
  int d1 = lc[v], d2 = rc[v];
  if (!comp(c1, c2))
    swap(c1, c2);
  if (!comp(d1, d2))
    swap(d1, d2);

  if (comp(c1, d1))
    return memo_c[u][v] = true;
  if (comp(d1, c1))
    return memo_c[u][v] = false;

  if (comp(c2, d2))
    return memo_c[u][v] = true;
  if (comp(d2, c2))
    return memo_c[u][v] = false;

  return memo_c[u][v] = false;
}

void manip(int u, int left) {
  if (u == -1)
    return;
  if (lc[u] == -1)
    return;
  assert(rc[u] != -1);
  if (left && comp(rc[u], lc[u])) {
    swap(lc[u], rc[u]);
  } else if (!left && comp(lc[u], rc[u])) {
    swap(lc[u], rc[u]);
  }
  manip(lc[u], 1);
  manip(rc[u], 0);
}

string to_str(int u) {
  if (lc[u] == -1) {
    return "x";
  } else {
    return "(" + to_str(lc[u]) + " " + to_str(rc[u]) + ")";
  }
}

void init() {
  lc.clear();
  rc.clear();
  roots.clear();
  memset(called, 0, sizeof(called));
  memset(memo_s, 0, sizeof(memo_s));
  memset(memo_c, -1, sizeof(memo_c));
}

int main() {
  string s;
  while (getline(cin, s)) {
    if (s[0] == '0')
      break;
    init();
    // cerr << "parse" << endl;
    parse(s, 0);
    int n = lc.size();
    roots.resize(n);
    // cerr << "roots" << endl;
    calc_roots(0);
    // cerr << "manip" << endl;
    manip(0, 1);
    // cerr << "to_str" << endl;
    cout << to_str(0) << endl;
  }
  return 0;
}

Error: -11

Fixed submission:

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
using namespace std;
typedef long long LL;

vector<int> lc;
vector<int> rc;
void skip(const string &s, int &k, char c) {
  if (k >= s.size()) {
    cerr << "index " << k << " but s.size() = " << s.size() << endl;
    assert(false);
  }
  if (s[k] != c) {
    cerr << "assert " << c << " but " << s[k] << endl;
    assert(false);
  }
  k++;
}
pair<int, int> parse(const string &s, int k) {
  if (s[k] == '(') {
    int v = lc.size();
    lc.push_back(-1);
    rc.push_back(-1);

    auto lcp = parse(s, k + 1);
    k = lcp.first;
    skip(s, k, ' ');
    auto rcp = parse(s, k);
    k = rcp.first;
    skip(s, k, ')');

    lc[v] = lcp.second;
    rc[v] = rcp.second;

    return make_pair(k, v);
  } else if (s[k] == 'x') {
    int v = lc.size();
    lc.push_back(-1);
    rc.push_back(-1);
    return make_pair(k + 1, v);
  } else {
    cerr << "s[" << k << "] = " << s[k] << endl;
    assert(false);
  }
}

int called[200][200] = {};
bool memo[200][200] = {};
bool check(int u, int v) {
  if (u == v)
    return true;
  if (u == -1 || v == -1)
    return false;

  if (u > v)
    swap(u, v);

  assert(called[u][v] != 1);
  if (called[u][v] != 0)
    return memo[u][v];
  called[u][v] = 1;

  memo[u][v] = false;

  if (check(lc[u], lc[v]) && check(rc[u], rc[v])) {
    memo[u][v] = true;
    goto RET;
  }

  if (check(lc[u], rc[v]) && check(rc[u], lc[v])) {
    memo[u][v] = true;
    goto RET;
  }

RET:
  called[u][v] = 2;
  return memo[u][v];
}

vector<vector<int>> roots;
void calc_roots(int u) {
  if (u == -1)
    return;
  roots[u].push_back(u);
  if (lc[u] == -1)
    return;
  calc_roots(lc[u]);
  calc_roots(rc[u]);
  roots[u].insert(roots[u].end(), roots[lc[u]].begin(), roots[lc[u]].end());
  roots[u].insert(roots[u].end(), roots[rc[u]].begin(), roots[rc[u]].end());
  vector<int> nr;

  for (int a : roots[u]) {
    bool ok = true;
    for (int b : nr) {
      if (check(a, b)) {
        ok = false;
      }
    }
    if (ok)
      nr.push_back(a);
  }
  roots[u].swap(nr);
}

typedef long long LL;
pair<LL, LL> memo_s[200];
pair<LL, LL> calc_sims(int r) {
  if (memo_s[r].second != 0)
    return memo_s[r];
  int u = lc[r], v = rc[r];
  if (u == -1) {
    assert(v == -1);
    return make_pair(0LL, 1LL);
  }
  assert(v != -1);

  int all = roots[u].size() + roots[v].size();
  int same = 0;
  for (int a : roots[u]) {
    int same_cnt = 0;
    for (int b : roots[v]) {
      if (check(a, b)) {
        same_cnt++;
        same++;
      }
    }
    assert(same_cnt <= 1);
  }
  int type = all - same;
  return memo_s[r] = pair<LL, LL>(same, type);
}

// u < v (sims)
bool comp(pair<LL, LL> a, pair<LL, LL> b) {
  return a.first * b.second < a.second * b.first;
}
bool eq(pair<LL, LL> a, pair<LL, LL> b) { return !comp(a, b) && !comp(b, a); }

int memo_c[200][200];
bool comp(int u, int v) {
  if (memo_c[u][v] != -1) {
    return memo_c[u][v];
  }
  auto a = calc_sims(u);
  auto b = calc_sims(v);
  if (comp(a, b))
    return memo_c[u][v] = true;
  if (comp(b, a))
    return memo_c[u][v] = false;
  if (lc[u] == -1) {
    assert(lc[v] == -1);
    return memo_c[u][v] = false;
  }

  int c1 = lc[u], c2 = rc[u];
  int d1 = lc[v], d2 = rc[v];
  if (comp(c1, c2))
    swap(c1, c2);
  if (comp(d1, d2))
    swap(d1, d2);

  if (comp(c1, d1))
    return memo_c[u][v] = true;
  if (comp(d1, c1))
    return memo_c[u][v] = false;

  if (comp(c2, d2))
    return memo_c[u][v] = true;
  if (comp(d2, c2))
    return memo_c[u][v] = false;

  return memo_c[u][v] = false;
}

void manip(int u, int left) {
  if (u == -1)
    return;
  if (lc[u] == -1)
    return;
  assert(rc[u] != -1);
  if (left && comp(rc[u], lc[u])) {
    swap(lc[u], rc[u]);
  } else if (!left && comp(lc[u], rc[u])) {
    swap(lc[u], rc[u]);
  }
  manip(lc[u], 1);
  manip(rc[u], 0);
}

string to_str(int u) {
  if (lc[u] == -1) {
    return "x";
  } else {
    return "(" + to_str(lc[u]) + " " + to_str(rc[u]) + ")";
  }
}

void init() {
  lc.clear();
  rc.clear();
  roots.clear();
  memset(called, 0, sizeof(called));
  memset(memo_s, 0, sizeof(memo_s));
  memset(memo_c, -1, sizeof(memo_c));
}

int main() {
  string s;
  ofstream ofs("/dev/null");
#ifndef DEBUG
  cerr.rdbuf(ofs.rdbuf());
#endif
  while (getline(cin, s)) {
    if (s[0] == '0')
      break;
    init();
    cerr << "parse" << endl;
    parse(s, 0);
    int n = lc.size();
    roots.resize(n);
    cerr << "roots" << endl;
    calc_roots(0);
    cerr << "manip" << endl;
    manip(0, 1);
    cerr << "to_str" << endl;
    cout << to_str(0) << endl;
  }
  return 0;
}