Problem p03108 (C++)

Buggy submission (status: Runtime Error):
// includes
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

// macros
#define ll long long int
#define pb emplace_back
#define mk make_pair
#define pq priority_queue
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end())

using namespace std;

//  types
typedef pair<int, int> P;
typedef pair<ll, int> Pl;
typedef pair<ll, ll> Pll;
typedef pair<double, double> Pd;

// constants
const int inf = 1e9;
const ll linf = 1LL << 50;
const double EPS = 1e-10;
const int mod = 1e9 + 7;

// solve
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

typedef struct UnionFind_ {
  vector<int> par;
  vector<int> rank_;
  vector<int> size_;
  UnionFind_(int n) : rank_(n, 0), size_(n, 1) {
    for (int i = 0; i < n; i++)
      par.push_back(i);
  }
  int find(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }
  bool same(int x, int y) {
    if (find(x) == find(y))
      return true;
    else
      return false;
  }
  bool unite(int x, int y) {
    int xp = find(x);
    int yp = find(y);
    if (xp == yp)
      return false;
    if (rank_[xp] > rank_[yp]) {
      par[yp] = xp;
      size_[xp] += size_[yp];
    } else if (rank_[xp] < rank_[yp]) {
      par[xp] = yp;
      size_[yp] += size_[xp];
    } else {
      par[yp] = xp;
      rank_[xp]++;
      size_[xp]++;
    }
    return true;
  }
} UnionFind;

int main(int argc, char const *argv[]) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<P> edge(m);
  rep(i, m) cin >> edge[i].first >> edge[i].second, edge[i].first--,
      edge[i].second--;
  vector<ll> ans(m);
  ll curr = (ll)n * (ll)(n - 1) / 2;
  UnionFind uf(n);
  for (int i = m - 1; i >= 0; i--) {
    ans[i] = curr;
    int a = edge[i].first, b = edge[i].second;
    if (!uf.same(a, b)) {
      curr -= (ll)uf.size_[uf.find(a)] * (ll)uf.size_[uf.find(b)];
      uf.unite(a, b);
    }
  }
  assert(curr == 0);
  for (int i = 0; i < m; i++) {
    cout << ans[i] << endl;
  }
  return 0;
}


Fixed submission:
// includes
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

// macros
#define ll long long int
#define pb emplace_back
#define mk make_pair
#define pq priority_queue
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end())

using namespace std;

//  types
typedef pair<int, int> P;
typedef pair<ll, int> Pl;
typedef pair<ll, ll> Pll;
typedef pair<double, double> Pd;

// constants
const int inf = 1e9;
const ll linf = 1LL << 50;
const double EPS = 1e-10;
const int mod = 1e9 + 7;

// solve
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

typedef struct UnionFind_ {
  vector<int> par;
  vector<int> rank_;
  vector<int> size_;
  UnionFind_(int n) : rank_(n, 0), size_(n, 1) {
    for (int i = 0; i < n; i++)
      par.push_back(i);
  }
  int find(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }
  bool same(int x, int y) {
    if (find(x) == find(y))
      return true;
    else
      return false;
  }
  bool unite(int x, int y) {
    int xp = find(x);
    int yp = find(y);
    if (xp == yp)
      return false;
    if (rank_[xp] > rank_[yp]) {
      par[yp] = xp;
      size_[xp] += size_[yp];
    } else if (rank_[xp] < rank_[yp]) {
      par[xp] = yp;
      size_[yp] += size_[xp];
    } else {
      par[yp] = xp;
      rank_[xp]++;
      size_[xp] += size_[yp];
    }
    return true;
  }
} UnionFind;

int main(int argc, char const *argv[]) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<P> edge(m);
  rep(i, m) cin >> edge[i].first >> edge[i].second, edge[i].first--,
      edge[i].second--;
  vector<ll> ans(m);
  ll curr = (ll)n * (ll)(n - 1) / 2;
  UnionFind uf(n);
  for (int i = m - 1; i >= 0; i--) {
    ans[i] = curr;
    int a = edge[i].first, b = edge[i].second;
    if (!uf.same(a, b)) {
      curr -= (ll)uf.size_[uf.find(a)] * (ll)uf.size_[uf.find(b)];
      uf.unite(a, b);
    }
  }
  assert(curr == 0);
  for (int i = 0; i < m; i++) {
    cout << ans[i] << endl;
  }
  return 0;
}