Problem p03108 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cctype>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

#define rep(i, n) for (ll i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (ll i = int(a); i < int(b); i++)
#define all(x) (x).begin(), (x).end()

typedef long long ll;

using namespace std;

#include <vector>
using namespace std;

struct UnionFind {
  vector<int> data;
  UnionFind(ll size) : data(size, -1) {}
  bool unionSet(ll x, ll 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(ll x, ll y) { return root(x) == root(y); }
  ll root(ll x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  ll size(ll x) { return -data[root(x)]; }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  // cout<<setprecision(10);
  ll N, M;
  cin >> N >> M;
  vector<pair<int, int>> edge(N);
  vector<ll> ans(M);
  rep(i, M) {
    ll a, b;
    cin >> a >> b;
    edge[i] = make_pair(a, b);
  }
  ans[M - 1] = ((ll)(N - 1)) * N / 2;
  UnionFind uf(N);
  for (ll i = M - 2; i >= 0; i--) {
    // cout<<"samegroup"<<endl;
    // cout<<edge[i+1].first-1<<" "<<edge[i+1].second-1<<endl;
    //  cout<<is_same_group(edge[i+1].first-1-1,edge[i+1].second-1-1)<<endl;

    if (uf.findSet(edge[i + 1].first - 1, edge[i + 1].second - 1)) {
      ans[i] = ans[i + 1];
      uf.unionSet(edge[i + 1].first - 1, edge[i + 1].second - 1);
    } else {
      ll sa = uf.size(edge[i + 1].first - 1);
      ll sb = uf.size(edge[i + 1].second - 1);
      // cout<<sa<<" "<<sb<<endl;
      ans[i] = ans[i + 1] - sa * sb;
      uf.unionSet(edge[i + 1].first - 1, edge[i + 1].second - 1);
    }
  }
  cout << endl;
  rep(i, M) { cout << ans[i] << '\n'; }
  cout << endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <cctype>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

#define rep(i, n) for (ll i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (ll i = int(a); i < int(b); i++)
#define all(x) (x).begin(), (x).end()

typedef long long ll;

using namespace std;

#include <vector>
using namespace std;

struct UnionFind {
  vector<int> data;
  UnionFind(ll size) : data(size, -1) {}
  bool unionSet(ll x, ll 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(ll x, ll y) { return root(x) == root(y); }
  ll root(ll x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  ll size(ll x) { return -data[root(x)]; }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  // cout<<setprecision(10);
  ll N, M;
  cin >> N >> M;
  vector<pair<int, int>> edge(M);
  vector<ll> ans(M);
  rep(i, M) {
    ll a, b;
    cin >> a >> b;
    edge[i] = make_pair(a, b);
  }
  ans[M - 1] = ((ll)(N - 1)) * N / 2;
  UnionFind uf(N);
  for (ll i = M - 2; i >= 0; i--) {
    // cout<<"samegroup"<<endl;
    // cout<<edge[i+1].first-1<<" "<<edge[i+1].second-1<<endl;
    //  cout<<is_same_group(edge[i+1].first-1-1,edge[i+1].second-1-1)<<endl;

    if (uf.findSet(edge[i + 1].first - 1, edge[i + 1].second - 1)) {
      ans[i] = ans[i + 1];
      uf.unionSet(edge[i + 1].first - 1, edge[i + 1].second - 1);
    } else {
      ll sa = uf.size(edge[i + 1].first - 1);
      ll sb = uf.size(edge[i + 1].second - 1);
      // cout<<sa<<" "<<sb<<endl;
      ans[i] = ans[i + 1] - sa * sb;
      uf.unionSet(edge[i + 1].first - 1, edge[i + 1].second - 1);
    }
  }
  cout << endl;
  rep(i, M) { cout << ans[i] << '\n'; }
  cout << endl;

  return 0;
}