Problem p01352 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define fi first
#define se second
#define repl(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rep(i, n) repl(i, 0, n)
#define all(x) (x).begin(), (x).end()
#define dbg(x) cerr << #x "=" << x << endl
#define mmax(x, y) (x > y ? x : y)
#define mmin(x, y) (x < y ? x : y)
#define maxch(x, y) x = mmax(x, y)
#define minch(x, y) x = mmin(x, y)
#define uni(x) x.erase(unique(all(x)), x.end())
#define exist(x, y) (find(all(x), y) != x.end())
#define bcnt __builtin_popcount

#define INF 1e16
#define mod 1000000007

#define B 10

struct UnionFind {
  vector<int> v;
  vector<int> sav;
  vector<int> hist;
  UnionFind(int n) : v(n, -1) {}
  void init() {
    for (int i = 0; i < v.size(); i++)
      v[i] = -1;
  }
  int find(int x) { return v[x] < 0 ? x : find(v[x]); }
  void rollback() {
    while (hist.size()) {
      v[hist.back()] = sav[hist.back()];
      hist.pop_back();
    }
  }
  void snapshot() {
    sav = v;
    hist.clear();
  }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return false;
    if (-v[x] < -v[y])
      swap(x, y);

    hist.push_back(x);
    hist.push_back(y);
    v[x] += v[y];
    v[y] = x;
    return true;
  }
  bool root(int x) { return v[x] < 0; }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return -v[find(x)]; }
};

struct query {
  int typ, u, v;
};

int N, Q;
vector<query> qs;
set<P> es;

int main() {
  cin >> N >> Q;
  rep(i, Q) {
    int t, u, v;
    cin >> t >> u >> v;
    qs.push_back((query){t, u, v});
  }

  for (int sq = 0; sq < Q; sq += B) {
    map<P, bool> qes;
    set<P> est;
    UnionFind uf(N);
    for (int i = sq; i < min(sq + B, Q); i++) {
      query q = qs[i];
      if (q.typ <= 2)
        qes[P(q.u, q.v)] = true;
    }

    for (P e : es) {
      if (qes[P(e.fi, e.se)]) {
        est.insert(e);
      } else {
        uf.unite(e.fi, e.se);
      }
    }
    uf.snapshot();

    for (int i = sq; i < min(sq + B, Q); i++) {
      query q = qs[i];
      if (q.typ == 1) {
        est.insert(P(q.u, q.v));
        es.insert(P(q.u, q.v));
      } else if (q.typ == 2) {
        est.erase(P(q.u, q.v));
        es.erase(P(q.u, q.v));
      } else {
        uf.rollback();
        for (P e : est) {
          uf.unite(e.fi, e.se);
        }

        if (uf.same(q.u, q.v))
          cout << "YES" << endl;
        else
          cout << "NO" << endl;
      }
    }
  }

  return 0;
}


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

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define fi first
#define se second
#define repl(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rep(i, n) repl(i, 0, n)
#define all(x) (x).begin(), (x).end()
#define dbg(x) cerr << #x "=" << x << endl
#define mmax(x, y) (x > y ? x : y)
#define mmin(x, y) (x < y ? x : y)
#define maxch(x, y) x = mmax(x, y)
#define minch(x, y) x = mmin(x, y)
#define uni(x) x.erase(unique(all(x)), x.end())
#define exist(x, y) (find(all(x), y) != x.end())
#define bcnt __builtin_popcount

#define INF 1e16
#define mod 1000000007

#define B 200

struct UnionFind {
  vector<int> v;
  vector<int> sav;
  vector<int> hist;
  UnionFind(int n) : v(n, -1) {}
  void init() {
    for (int i = 0; i < v.size(); i++)
      v[i] = -1;
  }
  int find(int x) { return v[x] < 0 ? x : find(v[x]); }
  void rollback() {
    while (hist.size()) {
      v[hist.back()] = sav[hist.back()];
      hist.pop_back();
    }
  }
  void snapshot() {
    sav = v;
    hist.clear();
  }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return false;
    if (-v[x] < -v[y])
      swap(x, y);

    hist.push_back(x);
    hist.push_back(y);
    v[x] += v[y];
    v[y] = x;
    return true;
  }
  bool root(int x) { return v[x] < 0; }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return -v[find(x)]; }
};

struct query {
  int typ, u, v;
};

int N, Q;
vector<query> qs;
set<P> es;

int main() {
  cin >> N >> Q;
  rep(i, Q) {
    int t, u, v;
    cin >> t >> u >> v;
    qs.push_back((query){t, u, v});
  }

  for (int sq = 0; sq < Q; sq += B) {
    map<P, bool> qes;
    set<P> est;
    UnionFind uf(N);
    for (int i = sq; i < min(sq + B, Q); i++) {
      query q = qs[i];
      if (q.typ <= 2)
        qes[P(q.u, q.v)] = true;
    }

    for (P e : es) {
      if (qes[P(e.fi, e.se)]) {
        est.insert(e);
      } else {
        uf.unite(e.fi, e.se);
      }
    }
    uf.snapshot();

    for (int i = sq; i < min(sq + B, Q); i++) {
      query q = qs[i];
      if (q.typ == 1) {
        est.insert(P(q.u, q.v));
        es.insert(P(q.u, q.v));
      } else if (q.typ == 2) {
        est.erase(P(q.u, q.v));
        es.erase(P(q.u, q.v));
      } else {
        uf.rollback();
        for (P e : est) {
          uf.unite(e.fi, e.se);
        }

        if (uf.same(q.u, q.v))
          cout << "YES" << endl;
        else
          cout << "NO" << endl;
      }
    }
  }

  return 0;
}