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

// Limit: 32768K / 8000ms
#include <cstdio>
#include <vector>
using namespace std;

class UnionFindTree {
public:
  UnionFindTree(int n) {
    par = vector<int>(n);
    for (int i = 0; i < n; i++)
      par[i] = i;
  }
  int find(int x) {
    if (x == par[x])
      return x;
    else
      return par[x] = find(par[x]);
  }
  void unite(int x, int y) {
    int rx = find(x), ry = find(y);
    if (rx != ry)
      par[ry] = rx;
  }
  bool same(int x, int y) { return find(x) == find(y); }

private:
  vector<int> par;
};

vector<vector<int>> G;
vector<bool> marked;
UnionFindTree tree(0);

long long solve(int N, int Q, vector<int> &parent,
                vector<pair<bool, int>> &queries) {
  for (int i = 0; i < Q; i++) {
    if (queries[i].first == false)
      marked[queries[i].second - 1] = true;
  }

  tree = UnionFindTree(N);
  for (int i = 0; i < N; i++) {
    if (!marked[i])
      tree.unite(parent[i], i);
  }

  long long res = 0;
  for (int i = Q - 1; i >= 0; i--) {
    int x = queries[i].second - 1;
    if (queries[i].first == false) {
      tree.unite(parent[x], x);
    } else {
      res += tree.find(x) + 1;
    }
  }
  return res;
}

int main() {
  while (true) {
    int N, Q;
    scanf("%d %d", &N, &Q);
    if (N == 0 && Q == 0)
      break;

    vector<int> parent(N);
    G = vector<vector<int>>(N);
    for (int i = 1; i < N; i++) {
      int n;
      scanf("%d", &n);
      G[n - 1].push_back(i);
      parent[i] = n - 1;
    }

    marked = vector<bool>(N);
    marked[0] = true;
    vector<pair<bool, int>> queries(Q);
    char buf[2];
    int qnum = 0;
    for (int i = 0; i < Q; i++) {
      int n;
      scanf("%s %d", buf, &n);
      if (buf[0] == 'Q') {
        queries[qnum++] = make_pair(true, n);
      } else if (!marked[n - 1]) {
        marked[n - 1] = true;
        queries[qnum++] = make_pair(false, n);
      }
    }
    Q = qnum;
    queries.resize(Q);
    long long ans = solve(N, Q, parent, queries);
    printf("%lld\\n", ans);
  }
}

Error: TLE

Fixed submission:

// Limit: 32768K / 8000ms
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;

typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef long long LL;
#define ALL(a) (a).begin(), (a).end()
#define REP(i, n) for (int i = 0; i < (n); ++i)
const double EPS = 1e-10;
const double PI = acos(-1.0);
#define dump(x)                                                                \\
  cerr << "  (L" << __LINE__ << ") " << #x << " = " << (x) << endl;
#define dumpv(x)                                                               \\
  cerr << "  (L" << __LINE__ << ") " << #x << " = ";                           \\
  REP(q, (x).size()) cerr << (x)[q] << " ";                                    \\
  cerr << endl;
template <typename T1, typename T2>
ostream &operator<<(ostream &s, const pair<T1, T2> &d) {
  return s << "(" << d.first << "," << d.second << ")";
}

class UnionFindTree {
public:
  UnionFindTree(int n) {
    rank = vector<int>(n, 0);
    par = vector<int>(n);
    for (int i = 0; i < n; i++)
      par[i] = i;
  }
  int find(int x) {
    if (x == par[x])
      return x;
    else
      return par[x] = find(par[x]);
  }
  void unite(int x, int y) {
    int rx = find(x), ry = find(y);
    if (rx != ry)
      par[ry] = rx;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  void print() {
    for (int i = 0; i < par.size(); i++)
      cerr << find(i) << " ";
    cerr << endl;
  }

private:
  vector<int> par;
  vector<int> rank;
};

vector<vector<int>> G;
vector<bool> marked;
UnionFindTree tree(0);

void dfs(int idx, int par) {
  if (marked[idx]) {
    par = idx;
  } else {
    tree.unite(par, idx);
  }
  for (int i = 0; i < G[idx].size(); i++) {
    dfs(G[idx][i], par);
  }
}

LL solve(int N, int Q, vector<int> &parent, vector<pair<bool, int>> &queries) {
  marked = vector<bool>(N);
  marked[0] = true;
  for (int i = 0; i < Q; i++) {
    if (queries[i].first == false)
      marked[queries[i].second - 1] = true;
  }
  tree = UnionFindTree(N);
  // dfs(0, -1);
  for (int i = 0; i < N; i++) {
    if (!marked[i])
      tree.unite(parent[i], i);
  }

  tree.print();

  LL res = 0;
  for (int i = Q - 1; i >= 0; i--) {
    int x = queries[i].second - 1;
    if (queries[i].first == false) {
      tree.unite(parent[x], x);
      tree.print();
    } else {
      res += tree.find(x) + 1;
    }
  }
  return res;
}

int main() {
  while (true) {
    int N, Q;
    scanf("%d %d", &N, &Q);
    if (N == 0 && Q == 0)
      break;

    vector<int> parent(N);
    G = vector<vector<int>>(N);
    for (int i = 1; i < N; i++) {
      int n;
      scanf("%d", &n);
      G[n - 1].push_back(i);
      parent[i] = n - 1;
    }
    vector<pair<bool, int>> queries(Q);
    char buf[2];
    for (int i = 0; i < Q; i++) {
      int n;
      scanf("%s %d", buf, &n);
      if (strcmp(buf, "Q") == 0) {
        queries[i] = make_pair(true, n);
      } else {
        queries[i] = make_pair(false, n);
      }
    }
    LL ans = solve(N, Q, parent, queries);
    printf("%lld\\n", ans);
  }
}