Problem p01288 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <iostream>
#include <vector>
using namespace std;
// ------ Class ------ //
class QuickUnionFind {
private:
  unsigned size_;
  std::vector<unsigned> g;
  std::vector<std::vector<unsigned>> v;

public:
  QuickUnionFind()
      : size_(0), g(std::vector<unsigned>()),
        v(std::vector<std::vector<unsigned>>()){};
  QuickUnionFind(unsigned size__) : size_(size__) {
    g.resize(size_);
    v.resize(size_);
    for (unsigned i = 0; i < size_; i++)
      g[i] = i, v[i] = {i};
  };
  unsigned size() { return size_; }
  unsigned root(unsigned x) { return g[x]; }
  unsigned size(unsigned x) { return v[x].size(); }
  bool same(unsigned x, unsigned y) { return g[x] == g[y]; }
  void unite(unsigned x, unsigned y) {
    x = g[x], y = g[y];
    if (x == y)
      return;
    if (v[x].size() < v[y].size())
      std::swap(x, y);
    v[x].insert(v[x].end(), v[y].begin(), v[y].end());
    for (auto &e : v[y])
      g[e] = x;
    v[y].clear();
  }
  bool operator==(const QuickUnionFind &u) { return g == u.g; }
  bool operator!=(const QuickUnionFind &u) { return g != u.g; }
};

long long n, q, a[200000], b[200000];
char J[200000];
int K[200000];
int main() {
  while (true) {
    cin >> n >> q;
    if (n == 0 && q == 0)
      break;
    for (int i = 0; i < 200000; i++)
      b[i] = 0;
    for (int i = 2; i <= n; i++)
      cin >> a[i];
    for (int i = 0; i < q; i++) {
      cin >> J[i] >> K[i];
      if (J[i] == 'M')
        b[K[i]]++;
    }
    QuickUnionFind UF(n + 2);
    long long sum = 0;
    for (int i = 2; i <= n; i++) {
      if (b[i] == 0)
        UF.unite(i, a[i]);
    }
    for (int i = q - 1; i >= 0; i--) {
      if (J[i] == 'M' && K[i] != 1) {
        b[K[i]]--;
        if (b[K[i]] == 0)
          UF.unite(a[K[i]], K[i]);
      }
      if (J[i] == 'Q') {
        int D = K[i];
        while (true) {
          if (UF.same(a[D], K[i]) == false) {
            sum += D;
            break;
          }
          D = a[D];
        }
      }
    }
    cout << sum << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <iostream>
#include <vector>
using namespace std;
// ------ Class ------ //
class QuickUnionFind {
private:
  unsigned size_;
  std::vector<unsigned> g;
  std::vector<std::vector<unsigned>> v;

public:
  QuickUnionFind()
      : size_(0), g(std::vector<unsigned>()),
        v(std::vector<std::vector<unsigned>>()){};
  QuickUnionFind(unsigned size__) : size_(size__) {
    g.resize(size_);
    v.resize(size_);
    for (unsigned i = 0; i < size_; i++)
      g[i] = i, v[i] = {i};
  };
  unsigned size() { return size_; }
  unsigned root(unsigned x) { return g[x]; }
  unsigned size(unsigned x) { return v[x].size(); }
  bool same(unsigned x, unsigned y) { return g[x] == g[y]; }
  void unite(unsigned x, unsigned y) {
    x = g[x], y = g[y];
    if (x == y)
      return;
    if (v[x].size() < v[y].size())
      std::swap(x, y);
    v[x].insert(v[x].end(), v[y].begin(), v[y].end());
    for (auto &e : v[y])
      g[e] = x;
    v[y].clear();
  }
  bool operator==(const QuickUnionFind &u) { return g == u.g; }
  bool operator!=(const QuickUnionFind &u) { return g != u.g; }
};

long long n, q, a[200000], b[200000];
char J[200000];
int K[200000], R[200000];
int main() {
  while (true) {
    cin >> n >> q;
    if (n == 0 && q == 0)
      break;
    for (int i = 0; i < 200000; i++)
      K[i] = 0;
    for (int i = 2; i <= n; i++)
      cin >> a[i];
    for (int i = 0; i < q; i++) {
      cin >> J[i] >> K[i];
      if (J[i] == 'M')
        b[K[i]] = 1;
    }
    for (int i = 1; i <= n; i++) {
      int D = i;
      for (int j = 0; j < 50; j++)
        D = a[i];
      R[i] = D;
    }
    QuickUnionFind UF(n + 2);
    long long sum = 0;
    for (int i = 2; i <= n; i++) {
      if (b[i] == 0)
        UF.unite(i, a[i]);
    }
    for (int i = q - 1; i >= 0; i--) {
      if (J[i] == 'M')
        UF.unite(a[K[i]], K[i]);
      if (J[i] == 'Q') {
        int D = K[i];
        bool flag = true;
        while (true) {
          if (UF.same(R[D], K[i]) == false) {
            while (true) {
              if (UF.same(a[D], K[i]) == false) {
                sum += D;
                flag = false;
                break;
              }
              D = a[D];
            }
            if (flag == false)
              break;
          }
          D = R[D];
        }
      }
    }
    cout << sum << endl;
  }
  return 0;
}