Problem p03108 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#include <cmath>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define ll long long
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define FORR(i, a, b) for (ll i = (a); i <= (b); i++)
#define repR(i, n) for (ll i = n; i >= 0; i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define F first
#define S second
#define pb push_back
#define pu push
#define COUT(x) cout << (x) << endl
#define PQ priority_queue<ll>
#define PQR priority_queue<ll, vector<ll>, greater<ll>>
#define YES(n) cout << ((n) ? "YES" : "NO") << endl
#define Yes(n) cout << ((n) ? "Yes" : "No") << endl
#define mp make_pair
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
#define sz(x) (int)(x).size()
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const ll MOD = 1000000007LL;
const ll INF = 1LL << 60;
using vll = vector<ll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvll = vector<vll>;
using vstr = vector<string>;
using pll = pair<ll, ll>;
using vc = vector<char>;
using vvc = vector<vc>;
ll dx[4] = {0, 1, 0, -1};
ll dy[4] = {1, 0, -1, 0};
template <typename T> struct UnionFind {
  vector<T> par;
  vector<T> rank;
  vector<T> sizes;
  UnionFind(T n) : par(n), rank(n, 0), sizes(n, 1) {
    for (T i = 0; i < n; i++) {
      par[i] = i;
    }
  }
  T root(T x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool unite(T x, T y) {
    if (x == y)
      return false;
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (rank[x] < rank[y])
      swap(x, y);
    if (rank[x] == rank[y])
      rank[x]++;
    par[y] = x;
    sizes[x] = sizes[x] + sizes[y];
    return true;
  }
  bool same(T x, T y) { return root(x) == root(y); }
  T size(T x) { return sizes[root(x)]; }
};
int main() {
  ll n, m;
  cin >> n >> m;
  vll a(m), b(m);
  rep(i, m) cin >> a[i] >> b[i];
  vll ans(m);
  UnionFind<ll> uf(n + 1);
  ans[m - 1] = (n * (n - 1) / 2);
  for (int i = m - 1; i > 0; i++) {
    if (uf.same(a[i], b[i])) {
      ans[i - 1] = ans[i];
    } else {
      ans[i - 1] = ans[i] - uf.size(a[i]) * uf.size(b[i]);
      uf.unite(a[i], b[i]);
    }
  }
  rep(i, m) { COUT(ans[i]); }
}


Fixed submission:
#include <bits/stdc++.h>
#include <cmath>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define ll long long
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define FORR(i, a, b) for (ll i = (a); i <= (b); i++)
#define repR(i, n) for (ll i = n; i >= 0; i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define F first
#define S second
#define pb push_back
#define pu push
#define COUT(x) cout << (x) << endl
#define PQ priority_queue<ll>
#define PQR priority_queue<ll, vector<ll>, greater<ll>>
#define YES(n) cout << ((n) ? "YES" : "NO") << endl
#define Yes(n) cout << ((n) ? "Yes" : "No") << endl
#define mp make_pair
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
#define sz(x) (int)(x).size()
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const ll MOD = 1000000007LL;
const ll INF = 1LL << 60;
using vll = vector<ll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvll = vector<vll>;
using vstr = vector<string>;
using pll = pair<ll, ll>;
using vc = vector<char>;
using vvc = vector<vc>;
ll dx[4] = {0, 1, 0, -1};
ll dy[4] = {1, 0, -1, 0};
template <typename T> struct UnionFind {
  vector<T> par;
  vector<T> rank;
  vector<T> sizes;
  UnionFind(T n) : par(n), rank(n, 0), sizes(n, 1) {
    for (T i = 0; i < n; i++) {
      par[i] = i;
    }
  }
  T root(T x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool unite(T x, T y) {
    if (x == y)
      return false;
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (rank[x] < rank[y])
      swap(x, y);
    if (rank[x] == rank[y])
      rank[x]++;
    par[y] = x;
    sizes[x] = sizes[x] + sizes[y];
    return true;
  }
  bool same(T x, T y) { return root(x) == root(y); }
  T size(T x) { return sizes[root(x)]; }
};
int main() {
  ll n, m;
  cin >> n >> m;
  vll a(m), b(m);
  rep(i, m) cin >> a[i] >> b[i];
  vll ans(m);
  UnionFind<ll> uf(n + 1);
  ans[m - 1] = (n * (n - 1) / 2);
  for (int i = m - 1; i > 0; i--) {
    if (uf.same(a[i], b[i])) {
      ans[i - 1] = ans[i];
    } else {
      ans[i - 1] = ans[i] - uf.size(a[i]) * uf.size(b[i]);
      uf.unite(a[i], b[i]);
    }
  }
  rep(i, m) { COUT(ans[i]); }
}