Problem p03108 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, begin, end) for (ll i = (begin); i < (end); i++)
#define REP(i, n) FOR(i, 0, n)
#define IFOR(i, begin, end) for (ll i = (begin)-1; i >= (end); i--)
#define IREP(i, n) IFOR(i, n, 0)
#define SORT(a) sort(a.begin(), a.end())
#define ISORT(a) sort(a.begin(), a.end(), greater<ll>())
#define REVERSE(a) reverse(a.begin(), a.end())
#define debug(x) cout << #x << "=" << x << endl;
#define vdebug(v)                                                              \
  cout << #v << "=(" << ;                                                      \
  REP(i_debug, v.size()) { cout << v[i_debug] << ","; }                        \
  cout << ")" << endl;
#define mdebug(m)                                                              \
  cout << #m << "=" << endl;                                                   \
  REP(i_debug, m.size()) {                                                     \
    REP(j_debug, m[i_debug].size()) { cout << m[i_debug][j_debug] << ","; }    \
    cout << endl;                                                              \
  }
#define Max(a, b) a = max(a, b)
#define Min(a, b) a = min(a, b)

#define ll long long
#define f first
#define s second
#define pb push_back
#define INF 1000000000000000000

using vec = vector<ll>;
using mat = vector<vec>;
using Pii = pair<ll, ll>;
using PiP = pair<ll, Pii>;
using PPi = pair<Pii, ll>;
using bvec = vector<bool>;
using Pvec = vector<Pii>;
ll mod = 1000000007;

struct UnionFind {
  vector<ll> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
  vector<ll> memnum;

  UnionFind(ll N) { // 最初は全てが根であるとして初期化
    init(N);
  }

  void init(ll N) {
    par.resize(N);
    memnum.resize(N);
    for (ll i = 0; i < N; i++) {
      par[i] = i;
      memnum[i] = 1;
    }
  }

  ll root(ll x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
    if (par[x] == x)
      return x;
    return par[x] = root(par[x]);
  }

  void unite(ll x, ll y) { // xとyの木を併合
    ll rx = root(x);       // xの根をrx
    ll ry = root(y);       // yの根をry
    if (rx == ry)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま
    par[rx] =
        ry; // xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    //
    memnum[ry] += memnum[rx];
  }

  bool same(ll x, ll y) { // 2つのデータx, yが属する木が同じならtrueを返す
    ll rx = root(x);
    ll ry = root(y);
    return rx == ry;
  }

  //////////////

  bool is_root(ll x) { return par[x] == x; }

  ll num(ll x) { return memnum[root(x)]; }
};

ll combi(ll n, ll k) {
  if (n == k || k == 0)
    return 1;
  else {
    return combi(n - 1, k - 1) + combi(n - 1, k);
  }
}
int main() {
  // 入力
  ll N, M;
  cin >> N >> M;
  vec A(M), B(M);
  UnionFind tree(N);
  REP(i, M) { cin >> A[i] >> B[i]; }

  vec ans(M, 0);
  ans[M - 1] = N * (N - 1) / 2;
  IFOR(i, M, 1) {
    if (!tree.same(A[i], B[i])) {
      ans[i - 1] = ans[i] - tree.num(A[i]) * tree.num(B[i]);
    } else
      ans[i - 1] = ans[i];
    // debug(tree.num(A[i], N));
    tree.unite(A[i], B[i]);
  }

  REP(i, M) { cout << ans[i] << endl; }

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, begin, end) for (ll i = (begin); i < (end); i++)
#define REP(i, n) FOR(i, 0, n)
#define IFOR(i, begin, end) for (ll i = (begin)-1; i >= (end); i--)
#define IREP(i, n) IFOR(i, n, 0)
#define SORT(a) sort(a.begin(), a.end())
#define ISORT(a) sort(a.begin(), a.end(), greater<ll>())
#define REVERSE(a) reverse(a.begin(), a.end())
#define debug(x) cout << #x << "=" << x << endl;
#define vdebug(v)                                                              \
  cout << #v << "=(" << ;                                                      \
  REP(i_debug, v.size()) { cout << v[i_debug] << ","; }                        \
  cout << ")" << endl;
#define mdebug(m)                                                              \
  cout << #m << "=" << endl;                                                   \
  REP(i_debug, m.size()) {                                                     \
    REP(j_debug, m[i_debug].size()) { cout << m[i_debug][j_debug] << ","; }    \
    cout << endl;                                                              \
  }
#define Max(a, b) a = max(a, b)
#define Min(a, b) a = min(a, b)

#define ll long long
#define f first
#define s second
#define pb push_back
#define INF 1000000000000000000

using vec = vector<ll>;
using mat = vector<vec>;
using Pii = pair<ll, ll>;
using PiP = pair<ll, Pii>;
using PPi = pair<Pii, ll>;
using bvec = vector<bool>;
using Pvec = vector<Pii>;
ll mod = 1000000007;

struct UnionFind {
  vector<ll> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
  vector<ll> memnum;

  UnionFind(ll N) { // 最初は全てが根であるとして初期化
    init(N);
  }

  void init(ll N) {
    par.resize(N);
    memnum.resize(N);
    for (ll i = 0; i < N; i++) {
      par[i] = i;
      memnum[i] = 1;
    }
  }

  ll root(ll x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
    if (par[x] == x)
      return x;
    return par[x] = root(par[x]);
  }

  void unite(ll x, ll y) { // xとyの木を併合
    ll rx = root(x);       // xの根をrx
    ll ry = root(y);       // yの根をry
    if (rx == ry)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま
    par[rx] =
        ry; // xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    //
    memnum[ry] += memnum[rx];
  }

  bool same(ll x, ll y) { // 2つのデータx, yが属する木が同じならtrueを返す
    ll rx = root(x);
    ll ry = root(y);
    return rx == ry;
  }

  //////////////

  bool is_root(ll x) { return par[x] == x; }

  ll num(ll x) { return memnum[root(x)]; }
};

ll combi(ll n, ll k) {
  if (n == k || k == 0)
    return 1;
  else {
    return combi(n - 1, k - 1) + combi(n - 1, k);
  }
}
int main() {
  // 入力
  ll N, M;
  cin >> N >> M;
  vec A(M), B(M);
  UnionFind tree(N);
  REP(i, M) {
    cin >> A[i] >> B[i];
    A[i]--;
    B[i]--;
  }

  vec ans(M, 0);
  ans[M - 1] = N * (N - 1) / 2;
  IFOR(i, M, 1) {
    if (!tree.same(A[i], B[i])) {
      ans[i - 1] = ans[i] - tree.num(A[i]) * tree.num(B[i]);
    } else
      ans[i - 1] = ans[i];
    // debug(tree.num(A[i], N));
    tree.unite(A[i], B[i]);
  }

  REP(i, M) { cout << ans[i] << endl; }

  return 0;
}