Problem p03108 (C++)

Buggy submission (status: Runtime Error):

#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define bcnt __builtin_popcountll

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<ll, ll> Pll;
typedef pair<int, int> Pin;

ll INF = 1e16;
int inf = 1e9;
ll MOD = 1e9 + 7;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "{ ";
  REP(i, vec.size()) { os << vec[i] << " "; }
  os << "}";

  return os;
}

ll pow_mod(ll a, ll p) {
  ll res = 1;
  while (p) {
    if (p & 1)
      res = (res * a) % MOD;
    a = (a * a) % MOD;
    p >>= 1;
  }

  return res;
}

ll mod_inv(ll a, ll m) {
  ll b = m, u = 0, v = 1;
  while (a) {
    ll t = b / a;
    swap(b -= t * a, a);
    swap(u -= t * v, v);
  }

  return (u % m + m) % m;
}

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

void d_err() { cerr << endl; }

template <typename H, typename... T> void d_err(H h, T... t) {
  cerr << h << " ";
  d_err(t...);
}

#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", d_err(__VA_ARGS__);
#else
#define debug(...) 83;
#endif

struct UnionFind {
  vector<int> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int root(int x) {
    if (par[x] < 0)
      return x;
    return par[x] = root(x);
  }

  int issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);

    if (x == y)
      return false;

    // merge by size
    // force size of x to be bigger than that of y
    if (par[x] > par[y])
      swap(x, y);
    par[x] += par[y];
    par[y] = x;
  }

  int size(int x) { return -par[root(x)]; }
};

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  ll N, M;
  cin >> N >> M;

  int a[M], b[M];
  REP(i, M) { cin >> a[i] >> b[i], --a[i], --b[i]; }

  UnionFind uf(N);
  ll ans[M];
  ll cur = N * (N - 1) / 2;
  REP(i, M) {
    ans[M - i - 1] = cur;

    int ca = a[M - i - 1], cb = b[M - i - 1];

    if (uf.issame(ca, cb))
      continue;

    ll as = uf.size(ca), bs = uf.size(cb);

    cur -= as * bs;

    uf.merge(ca, cb);
  }

  cout << fixed << setprecision(20);
  REP(i, M) cout << ans[i] << endl;
}


Fixed submission:

#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define bcnt __builtin_popcountll

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<ll, ll> Pll;
typedef pair<int, int> Pin;

ll INF = 1e16;
int inf = 1e9;
ll MOD = 1e9 + 7;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "{ ";
  REP(i, vec.size()) { os << vec[i] << " "; }
  os << "}";

  return os;
}

ll pow_mod(ll a, ll p) {
  ll res = 1;
  while (p) {
    if (p & 1)
      res = (res * a) % MOD;
    a = (a * a) % MOD;
    p >>= 1;
  }

  return res;
}

ll mod_inv(ll a, ll m) {
  ll b = m, u = 0, v = 1;
  while (a) {
    ll t = b / a;
    swap(b -= t * a, a);
    swap(u -= t * v, v);
  }

  return (u % m + m) % m;
}

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

void d_err() { cerr << endl; }

template <typename H, typename... T> void d_err(H h, T... t) {
  cerr << h << " ";
  d_err(t...);
}

#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", d_err(__VA_ARGS__);
#else
#define debug(...) 83;
#endif

struct UnionFind {
  vector<int> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int root(int x) {
    if (par[x] < 0)
      return x;
    return par[x] = root(par[x]);
  }

  int issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);

    if (x == y)
      return false;

    // merge by size
    // force size of x to be bigger than that of y
    if (par[x] > par[y])
      swap(x, y);
    par[x] += par[y];
    par[y] = x;
  }

  int size(int x) { return -par[root(x)]; }
};

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  ll N, M;
  cin >> N >> M;

  int a[M], b[M];
  REP(i, M) { cin >> a[i] >> b[i], --a[i], --b[i]; }

  UnionFind uf(N);
  ll ans[M];
  ll cur = N * (N - 1) / 2;
  REP(i, M) {
    ans[M - i - 1] = cur;

    int ca = a[M - i - 1], cb = b[M - i - 1];

    if (uf.issame(ca, cb))
      continue;

    ll as = uf.size(ca), bs = uf.size(cb);

    cur -= as * bs;

    uf.merge(ca, cb);
  }

  cout << fixed << setprecision(20);
  REP(i, M) cout << ans[i] << endl;
}