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

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

#define for_(i, a, b) for (int i = a; i < b; ++i)
#define for_rev(i, a, b) for (int i = a; i >= b; --i)
#define minit(a, b) memset(a, b, sizeof(a))

typedef long long lint;

struct UnionFind {
private:
  vector<int> data;

public:
  UnionFind(int _size) : data(_size, -1) {}

  bool unite(int _x, int _y) {
    _x = root(_x);
    _y = root(_y);
    if (_x != _y) {
      if (data[_y] < data[_x])
        swap(_x, _y);
      data[_x] += data[_y];
      data[_y] = _x;
    }
    return _x != _y;
  }

  bool same(int _x, int _y) { return root(_x) == root(_y); }

  int root(int _x) { return data[_x] < 0 ? _x : data[_x] = root(data[_x]); }

  int size(int _x) { return -data[root(_x)]; }
};

int N, Q, p[100010];
char q[100010];
int mark[100010], v[100010];
lint anc[100010];

void solve() {
  UnionFind uf(N);

  for_(i, 0, N) if (!mark[i]) uf.unite(i, p[i]);
  for_(i, 0, N) if (mark[i]) anc[uf.root(i)] = i + 1;

  lint ans = 0;

  for_rev(i, Q - 1, 0) {
    if (q[i] == 'M') {
      --mark[v[i]];
      if (!mark[v[i]]) {
        int tmp = anc[uf.root(p[v[i]])];
        uf.unite(v[i], p[v[i]]);
        anc[uf.root(v[i])] = tmp;
      }
    } else {
      ans += anc[uf.root(v[i])];
    }
  }

  cout << ans << endl;
}

int main() {
  while (scanf("%d %d", &N, &Q), N) {
    for_(i, 1, N) {
      scanf("%d", &p[i]);
      --p[i];
    }

    minit(mark, 0);
    mark[0] = 1;

    for_(i, 0, Q) {
      scanf("%s %d", &q[i], &v[i]);
      --v[i];
      if (q[i] == 'M')
        ++mark[v[i]];
    }

    solve();
  }

  return 0;
}

Error: 0

Fixed submission:

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

#define for_(i, a, b) for (int i = a; i < b; ++i)
#define size_of(a) (int)a.size()

typedef long long lint;
typedef vector<int> Array;
typedef pair<int, int> pii;

const int iINF = 1L << 30;

int N, Q;
vector<Array> edges;
int depth[100010], node_number[100010];
pii ranges[100010];

// lazy evaluate segment tree
struct SegmentTreeL {
private:
  typedef int data_type;
  static const data_type dINF = iINF;

  int st_size;
  vector<data_type> data;
  vector<data_type> lazy;

public:
  SegmentTreeL(int _size, data_type _init_val) {
    st_size = 1;
    while (st_size < _size)
      st_size *= 2;
    data.assign(2 * st_size - 1, _init_val);
    lazy.assign(2 * st_size - 1, 0);
  }

  data_type calculation(data_type _d1, data_type _d2) { return min(_d1, _d2); }

  void lazy_calculation(int _k, data_type _val) {
    if (lazy[_k] == 0)
      lazy[_k] = _val;
    else if (depth[lazy[_k]] < depth[_val])
      lazy[_k] = _val;
  }

  inline void lazy_evaluate(int _a, int _b, int _k) {
    // change for purpose
    if (lazy[_k] != 0) {
      data[_k] = lazy[_k];
      if (_k < st_size - 1) {
        lazy_calculation(2 * _k + 1, lazy[_k]);
        lazy_calculation(2 * _k + 2, lazy[_k]);
      }
    }
  }

  inline void update_at(int _k) {
    data[_k] = calculation(data[2 * _k + 1], data[2 * _k + 2]);
  }

  void update(int _a, int _b, data_type _x) {
    update(_a, _b, _x, 0, 0, st_size);
  }

  void update(int _a, int _b, data_type _x, int _k, int _l, int _r) {
    lazy_evaluate(_a, _b, _k);

    if (_r <= _a || _b <= _l)
      return;
    if (_a <= _l && _r <= _b) {
      lazy_calculation(_k, _x);
      lazy_evaluate(_a, _b, _k);
      return;
    }

    update(_a, _b, _x, 2 * _k + 1, _l, (_l + _r) / 2);
    update(_a, _b, _x, 2 * _k + 2, (_l + _r) / 2, _r);
    update_at(_k);
  }

  data_type query(int _a, int _b) { return query(_a, _b, 0, 0, st_size); }

  data_type query(int _a, int _b, int _k, int _l, int _r) {
    lazy_evaluate(_a, _b, _k);

    if (_r <= _a || _b <= _l)
      return dINF;

    if (_a <= _l && _r <= _b)
      return data[_k];

    data_type res = calculation(query(_a, _b, 2 * _k + 1, _l, (_l + _r) / 2),
                                query(_a, _b, 2 * _k + 2, (_l + _r) / 2, _r));
    update_at(_k);
    return res;
  }

  int size() { return st_size; }
};

int dfs(int v, int &nv, int dp) {
  depth[v] = dp;

  int e_size = size_of(edges[v]), mn = iINF;

  for_(i, 0, e_size) {
    int u = edges[v][i];
    mn = min(mn, dfs(u, nv, dp + 1));
  }

  ++nv;
  node_number[v] = nv;
  ranges[v] = pii(min(mn, nv), nv);

  return min(mn, nv);
}

void solve() {
  SegmentTreeL stl(N + 5, iINF);
  for_(i, 1, N + 1) stl.update(i, i + 1, 1);

  int nv = 0;
  dfs(1, nv, 0);

  lint ans = 0;

  for_(i, 0, Q) {
    char q;
    int v;
    scanf("%s %d", &q, &v);

    if (q == 'Q') {
      nv = node_number[v];
      ans += (lint)stl.query(nv, nv + 1);
    } else {
      pii rng = ranges[v];
      stl.update(rng.first, rng.second + 1, v);
    }
  }

  cout << ans << endl;
}

int main() {
  while (scanf("%d %d", &N, &Q), N) {
    edges.assign(N + 1, Array());

    for_(i, 2, N + 1) {
      int p;
      scanf("%d", &p);
      edges[p].push_back(i);
    }

    solve();
  }

  return 0;
}