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

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>

#define show(x) cerr << #x << " = " << x << endl

using namespace std;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "sz:" << v.size() << "\\n[";
  for (const auto &p : v) {
    os << p << ",";
  }
  os << "]\\n";
  return os;
}

template <typename S, typename T>
ostream &operator<<(ostream &os, const pair<S, T> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}

class DisjointSets {
public:
  DisjointSets(const int v) {
    m_parent.resize(v);
    m_rank.resize(v);
    m_size.resize(v);
    for (int i = 0; i < v; i++) {
      m_parent[i] = i;
      m_rank[i] = 0;
      m_size[i] = 1;
    }
  }

  bool same(const int a, const int b) { return find(a) == find(b); }

  int find(const int a) {
    if (m_parent[a] == a) {
      return a;
    } else {
      return m_parent[a] = find(m_parent[a]);
    }
  }

  void unite(const int a_, const int b_) {
    const int a = find(a_);
    const int b = find(b_);
    if (a == b) {
      return;
    }
    if (m_rank[a] > m_rank[b]) {
      m_parent[b] = a;
      m_size[a] += m_size[b];
    } else {
      m_parent[a] = b;
      m_size[b] += m_size[a];
    }
    if (m_rank[a] == m_rank[b]) {
      m_rank[b]++;
    }
  }

  int getSize(const int a) { return m_size[m_parent[a]]; }

private:
  vector<int> m_parent;
  vector<int> m_rank;
  vector<int> m_size;
};

struct Graph {
  Graph(const int n) { edge.resize(n); }
  void addEdge(const int from, const int to) { edge[from].push_back(to); }
  vector<vector<int>> edge;
};

void dfs(const int s, const Graph &g, const vector<bool> &marked,
         DisjointSets &uf, vector<int> &comp) {
  for (const int to : g.edge[s]) {
    if (not marked[to]) {
      const int root = uf.find(s);
      uf.unite(s, to);
      comp[uf.find(s)] = comp[root];
    }
    dfs(to, g, marked, uf, comp);
  }
}

int main() {
  while (true) {
    int N, Q;
    cin >> N >> Q;
    if (N == 0 and Q == 0) {
      break;
    }
    Graph g(N);
    vector<bool> marked(N, false);
    marked[0] = true;
    vector<int> parent(N, 0);
    for (int i = 1; i < N; i++) {
      int from;
      cin >> from;
      from--;
      parent[i] = from;
      g.addEdge(from, i);
    }

    vector<bool> visited(N, false);

    using P = pair<char, int>;
    vector<P> query;
    vector<int> comp(N, 0);
    for (int q = 0; q < Q; q++) {
      char c;
      int n;
      cin >> c >> n;
      n--;
      if (c == 'M') {
        if (marked[n]) {
          continue;
        }
        comp[n] = n;
        marked[n] = true;
      }
      query.push_back(make_pair(c, n));
    }

    DisjointSets uf(N);
    dfs(0, g, marked, uf, comp);

    reverse(query.begin(), query.end());
    long long sum = 0;
    for (const auto &q : query) {
      if (q.first == 'M') {
        const int s = q.second;
        const int par = parent[s];
        const int root = uf.find(par);
        uf.unite(par, s);
        comp[uf.find(s)] = comp[root];
      } else {
        sum += (comp[uf.find(q.second)] + 1);
      }
    }
    cout << sum << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>

using namespace std;

class DisjointSets {
public:
  DisjointSets(const int v) {
    m_parent.resize(v);
    m_rank.resize(v);
    m_size.resize(v);
    for (int i = 0; i < v; i++) {
      m_parent[i] = i;
      m_rank[i] = 0;
      m_size[i] = 1;
    }
  }

  bool same(const int a, const int b) { return find(a) == find(b); }

  int find(const int a) {
    if (m_parent[a] == a) {
      return a;
    } else {
      return m_parent[a] = find(m_parent[a]);
    }
  }

  void unite(const int a_, const int b_) {
    const int a = find(a_);
    const int b = find(b_);
    if (a == b) {
      return;
    }
    if (m_rank[a] > m_rank[b]) {
      m_parent[b] = a;
      m_size[a] += m_size[b];
    } else {
      m_parent[a] = b;
      m_size[b] += m_size[a];
    }
    if (m_rank[a] == m_rank[b]) {
      m_rank[b]++;
    }
  }

  int getSize(const int a) { return m_size[m_parent[a]]; }

private:
  vector<int> m_parent;
  vector<int> m_rank;
  vector<int> m_size;
};

struct Graph {
  Graph(const int n) { edge.resize(n); }
  void addEdge(const int from, const int to) { edge[from].push_back(to); }
  vector<vector<int>> edge;
};

void dfs(const int s, const Graph &g, const vector<bool> &marked,
         DisjointSets &uf, vector<int> &comp) {
  for (const int to : g.edge[s]) {
    if (not marked[to]) {
      uf.unite(s, to);
      comp[uf.find(s)] = comp[s];
    }
    dfs(to, g, marked, uf, comp);
  }
}

void make_dfs(const int s, const Graph &g_, Graph &g, Graph &revg,
              vector<bool> &visited) {
  visited[s] = true;
  for (const int to : g_.edge[s]) {
    if (visited[to]) {
      continue;
    }
    g.addEdge(s, to);
    revg.addEdge(to, s);
    make_dfs(to, g_, g, revg, visited);
  }
}

int main() {
  while (true) {
    int N, Q;
    cin >> N >> Q;
    if (N == 0 and Q == 0) {
      break;
    }
    Graph g_(N);
    vector<bool> marked(N, false);
    marked[0] = true;
    for (int i = 0; i < N - 1; i++) {
      int to;
      cin >> to;
      to--;
      g_.addEdge(to, i);
      g_.addEdge(i, to);
    }

    vector<bool> visited(N, false);
    Graph g(N);
    Graph revg(N);
    make_dfs(0, g_, g, revg, visited);

    using P = pair<char, int>;
    vector<P> query;
    vector<int> comp(N);
    for (int i = 0; i < N; i++) {
      comp[i] = 0;
    }
    vector<bool> drawn(N, false);
    drawn[0] = true;
    for (int q = 0; q < Q; q++) {
      char c;
      int n;
      cin >> c >> n;
      n--;
      if (c == 'M') {
        if (drawn[n]) {
          continue;
        }
        drawn[n] = true;
        comp[n] = n;
        marked[n] = true;
      }
      query.push_back(make_pair(c, n));
    }

    DisjointSets uf(N);
    dfs(0, g, marked, uf, comp);

    reverse(query.begin(), query.end());
    int sum = 0;
    for (const auto &q : query) {
      if (q.first == 'M') {

        const int s = q.second;
        const int par = revg.edge[s][0];
        uf.unite(par, s);
        comp[uf.find(s)] = comp[par];
      } else {
        sum += (comp[uf.find(q.second)] + 1);
      }
    }
    cout << sum << endl;
  }
  return 0;
}