Problem p03108 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define ll int64_t
const ll mod = 1000000007;

const ll LINF = 1e13;
const ll LLINF = 1e18;
const ll ALPHABET = 26;

template <class T> void Swap(T &r, T &l) {
  T tmp = r;
  r = l;
  l = tmp;
}

template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (T &x : vec)
    is >> x; // for(int i=0; i<vec.size(); i++) is >> x[i]; とかでもいい
  return is;
}

struct UnionFind {
  vector<int> data;
  UnionFind(int size)
      : data(size, -1) {
  } // 最初は全て-1 :-1なら根なので全て根:木のサイズが増えると-2-3-4となる
  bool unionSet(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 findSet(int x, int y) { // 要素xとyが同じ集合か　→　rootを調べれば解決
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0
               ? x
               : data[x] = root(
                     data[x]); //-1なら根、そうでないなら配列が指す場所へ移動
  }
  int size(int x) { return -data[root(x)]; }
};

int main() {
  long n, m;
  cin >> n >> m;

  vector<pair<long, long>> mp(m);

  for (int i = 0; i < m; ++i) {
    long a, b;
    cin >> a >> b;

    mp[i] = make_pair(a - 1, b - 1);
  }

  struct UnionFind uftree1(12); // 全部で12こ//最初は全部が根
  // 1と同じグループ
  //  uftree1.unionSet(1, 3);

  vector<long> ans;
  ll tmp = n * (n - 1) / 2;
  for (int i = m - 1; i >= 0; --i) {
    ans.push_back(tmp);
    long x = mp[i].first;
    long y = mp[i].second;
    if (uftree1.findSet(x, y)) {
    } else {
      long xs = uftree1.size(x);
      long ys = uftree1.size(y);

      tmp -= xs * ys;
      uftree1.unionSet(x, y);
    }
  }

  for (int i = m - 1; i >= 0; --i) {
    cout << ans[i] << endl;
  }

  // cout << ans << endl;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define ll int64_t
const ll mod = 1000000007;

const ll LINF = 1e13;
const ll LLINF = 1e18;
const ll ALPHABET = 26;

template <class T> void Swap(T &r, T &l) {
  T tmp = r;
  r = l;
  l = tmp;
}

template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (T &x : vec)
    is >> x; // for(int i=0; i<vec.size(); i++) is >> x[i]; とかでもいい
  return is;
}

struct UnionFind {
  vector<int> data;
  UnionFind(int size)
      : data(size, -1) {
  } // 最初は全て-1 :-1なら根なので全て根:木のサイズが増えると-2-3-4となる
  bool unionSet(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 findSet(int x, int y) { // 要素xとyが同じ集合か　→　rootを調べれば解決
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0
               ? x
               : data[x] = root(
                     data[x]); //-1なら根、そうでないなら配列が指す場所へ移動
  }
  int size(int x) { return -data[root(x)]; }
};

int main() {
  long n, m;
  cin >> n >> m;

  vector<pair<long, long>> mp(m);

  for (int i = 0; i < m; ++i) {
    long a, b;
    cin >> a >> b;

    mp[i] = make_pair(a - 1, b - 1);
  }

  struct UnionFind uftree1(n); // 全部で12こ//最初は全部が根
  // 1と同じグループ
  //  uftree1.unionSet(1, 3);

  vector<long> ans;
  ll tmp = n * (n - 1) / 2;
  for (int i = m - 1; i >= 0; --i) {
    ans.push_back(tmp);
    long x = mp[i].first;
    long y = mp[i].second;
    if (uftree1.findSet(x, y)) {
    } else {
      long xs = uftree1.size(x);
      long ys = uftree1.size(y);

      tmp -= xs * ys;
      uftree1.unionSet(x, y);
    }
  }

  for (int i = m - 1; i >= 0; --i) {
    cout << ans[i] << endl;
  }

  // cout << ans << endl;
}