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

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

#define Rep(b, e, i) for (int i = b; i <= e; i++)
#define Repr(e, b, i) for (int i = e; i >= b; i--)
#define rep(n, i) Rep(0, n - 1, i)
#define repr(n, i) Repr(n - 1, 0, i)
#define all(v) (v).begin(), (v).end()
#define pb(v) push_back(v)
#define uniq(v) (v).erase(unique(all(v)), (v).end())
#define bitcnt(x) __builtin_popcount(x)
#define fst first
#define snd second
#define Pqaz(T) priority_queue<T, vector<T>, greater<T>>
#define Pqza(T) priority_queue<T>
#define ENJYU                                                                  \\
  std::ios::sync_with_stdio(false);                                            \\
  std::cin.tie(0);

// vector の中身を出力
template <class T> ostream &operator<<(ostream &o, const vector<T> &v) {
  o << "{";
  for (int i = 0; i < (int)v.size(); i++)
    o << (i > 0 ? ", " : "") << v[i];
  o << "}";
  return o;
}

typedef long long ll;
typedef pair<char, ll> query;

ll N, Q, ans;

// parent, nearest marked ancestor, ismarked
vector<ll> par, nma, ism;
vector<query> q;

// find nearest marked ancestor (keiroasshuku at the same time)
ll find_nma(ll x) {
  if (nma[x] == x)
    return x;
  else
    return nma[x] = find_nma(par[x]);
}

void solve(void) {
  // ENJYU;
  while (cin >> N >> Q) {
    if (N == 0 && Q == 0)
      break;
    // init
    par.clear(), ism.clear(), nma.clear(), q.clear();
    par.resize(N), ism.resize(N), nma.resize(N), q.resize(Q);
    par[0] = 0, ism[0] = 1, nma[0] = 0;
    ans = 0LL;
    rep(N - 1, i) {
      cin >> par[i + 1];
      par[i + 1]--;
    }
    nma = par;

    // クエリ受け取り
    rep(Q, i) {
      cin >> q[i].fst >> q[i].snd;
      q[i].snd--;
      // 先にMARKしておく
      if (q[i].fst == 'M') {
        ism[q[i].snd]++;
        nma[q[i].snd] = q[i].snd;
      }
    }

    // クエリを逆から見ていくと、頂点の更新は根の方向にのみ行われるので、前回の結果を使える
    repr(Q, i) {
      if (q[i].fst == 'M') {
        ism[q[i].snd]--;
        if (ism[q[i].snd])
          continue;
        nma[q[i].snd] = find_nma(par[q[i].snd]);
        continue;
      }
      ans += find_nma(q[i].snd) + 1;
    }
    cout << ans << endl;
  }
}

int main(void) {
  solve();
  // cout << "yui(*-v・)yui" << endl;
  return 0;
}


Error: 0

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

#define Rep(b, e, i) for (int i = b; i <= e; i++)
#define Repr(e, b, i) for (int i = e; i >= b; i--)
#define rep(n, i) Rep(0, n - 1, i)
#define repr(n, i) Repr(n - 1, 0, i)
#define all(v) (v).begin(), (v).end()
#define pb(v) push_back(v)
#define uniq(v) (v).erase(unique(all(v)), (v).end())
#define bitcnt(x) __builtin_popcount(x)
#define fst first
#define snd second
#define Pqaz(T) priority_queue<T, vector<T>, greater<T>>
#define Pqza(T) priority_queue<T>
#define ENJYU                                                                  \\
  std::ios::sync_with_stdio(false);                                            \\
  std::cin.tie(0);

// vector の中身を出力
template <class T> ostream &operator<<(ostream &o, const vector<T> &v) {
  o << "{";
  for (int i = 0; i < (int)v.size(); i++)
    o << (i > 0 ? ", " : "") << v[i];
  o << "}";
  return o;
}

typedef long long ll;
typedef pair<char, ll> query;

ll N, Q, ans;

// parent, nearest marked ancestor, ismarked
vector<ll> par, nma;
vector<bool> ism;
vector<query> q;

// find nearest marked ancestor (keiroasshuku at the same time)
ll find_nma(ll x) {
  if (ism[x])
    return x;
  else
    return nma[x] = find_nma(par[x]);
}

void solve(void) {
  // ENJYU;
  while (cin >> N >> Q) {
    if (N == 0 && Q == 0)
      break;
    // init
    par.clear(), ism.clear(), nma.clear(), q.clear();
    par.resize(N), ism.resize(N), nma.resize(N), q.resize(Q);
    par[0] = 0, ism[0] = 1, nma[0] = 0;
    ans = 0LL;
    rep(N - 1, i) {
      cin >> par[i + 1];
      par[i + 1]--;
    }
    nma = par;

    // クエリ受け取り
    rep(Q, i) {
      cin >> q[i].fst >> q[i].snd;
      q[i].snd--;
      // 先にMARKしておく
      if (q[i].fst == 'M') {
        ism[q[i].snd] = 1;
        nma[q[i].snd] = q[i].snd;
      }
    }

    // クエリを逆から見ていくと、頂点の更新は根の方向にのみ行われるので、前回の結果を使える
    repr(Q, i) {
      if (q[i].fst == 'M') {
        ism[q[i].snd] = 0;
        // nma[q[i].snd] = find_nma(par[q[i].snd]);
        continue;
      }
      ans += find_nma(q[i].snd) + 1;
    }
    cout << ans << endl;
    break;
  }
}

int main(void) {
  solve();
  // cout << "yui(*-v・)yui" << endl;
  return 0;
}