Problem p03770 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1e9 + 7;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <class T> istream &operator>>(istream &is, vector<T> &v) {
  for (auto &i : v)
    is >> i;
  return is;
}
template <class T> ostream &operator<<(ostream &os, vector<T> &v) {
  const string delimiter = "\n";
  REP(i, v.size()) {
    os << v[i];
    if (i != v.size() - 1)
      os << delimiter;
  }
  return os;
}
/*--------------------template--------------------*/

const int INF = 1e9 + 1;

struct UnionFind {
  vector<int> par;
  UnionFind(int n) : par(n, -1) {}
  int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (par[y] < par[x])
      swap(x, y);
    if (par[x] == par[y])
      par[x]--;
    par[y] = x;
    if (find(x) != find(y))
      par[find(y)] = x;
  }
  int count() {
    int cnt = 0;
    REP(i, par.size()) if (par[i] < 0) cnt++;
    return cnt;
  }
  bool same(int x, int y) { return find(x) == find(y); }
};

template <int M> class Cyclic {
  using ll = long long;
  int n;
  static ll inv(ll a, ll p) {
    return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
  }

public:
  Cyclic() : n(0) { ; }
  Cyclic(int m) : n(m) {
    if (n >= M)
      n %= M;
    else if (n < 0)
      n = (n % M + M) % M;
  }
  operator int() const { return n; }
  bool operator==(const Cyclic &a) const { return n == a.n; }
  Cyclic operator+=(const Cyclic &a) {
    n += a.n;
    if (n >= M)
      n -= M;
    return *this;
  }
  Cyclic operator-=(const Cyclic &a) {
    n -= a.n;
    if (n < 0)
      n += M;
    return *this;
  }
  Cyclic operator*=(const Cyclic &a) {
    n = (ll(n) * a.n) % M;
    return *this;
  }
  Cyclic operator+(const Cyclic &a) const {
    Cyclic res = *this;
    return res += a;
  }
  Cyclic operator-(const Cyclic &a) const {
    Cyclic res = *this;
    return res -= a;
  }
  Cyclic operator*(const Cyclic &a) const {
    Cyclic res = *this;
    return res *= a;
  }
  Cyclic operator/(const Cyclic &a) const {
    return *this * Cyclic<M>(inv(a, M));
  }
  Cyclic operator^(int n) const {
    if (n == 0)
      return Cyclic(1);
    const Cyclic a = *this;
    Cyclic res = (a * a) ^ (n / 2);
    return n % 2 ? res * a : res;
  }
};

template <int M> Cyclic<M> fact(int n, bool sw = true) {
  static vector<Cyclic<M>> v1 = {1}, v2 = {1};
  if (n >= (int)v1.size()) {
    const int from = v1.size(), to = n + 1024;
    v1.reserve(to);
    v2.reserve(to);
    for (int i = from; i < to; ++i) {
      v1.push_back(v1.back() * Cyclic<M>(i));
      v2.push_back(v2.back() / Cyclic<M>(i));
    }
  }
  return sw ? v1[n] : v2[n];
}

template <int M> Cyclic<M> comb(int a, int b) {
  return fact<M>(a, true) * fact<M>(b, false) * fact<M>(a - b, false);
}

const int mod = 1000000007;
using Mod = Cyclic<mod>;

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  int n, x, y;
  cin >> n >> x >> y;
  vector<pii> v;
  REP(i, n) {
    int a, b;
    cin >> a >> b;
    v.emplace_back(b, a);
  }
  sort(ALL(v));
  map<int, pii> color_min; // color, <weight, index>
  tuple<int, int, int> all_min(INF, -1, -1),
      all_min2(INF, -1, -1); // weight, color, index
  REP(i, n) {
    int tw = v[i].first, tc = v[i].second;
    if (color_min.count(tc) == 0)
      color_min[tc] = pii(tw, i);

    if (get<0>(all_min) > tw) {
      if (tc != get<1>(all_min2))
        all_min2 = all_min;
      all_min = make_tuple(tw, tc, i);
    } else if (get<0>(all_min2) > tw && get<1>(all_min2) != tc) {
      all_min2 = make_tuple(tw, tc, i);
    }
  }
  assert(get<1>(all_min) != get<1>(all_min2));
  UnionFind uf(n);
  REP(i, n) {
    int tw = v[i].first, tc = v[i].second;
    if (color_min[tc].second != i && tw + color_min[tc].first <= x) {
      uf.unite(i, color_min[tc].second);
    }

    if (tc != get<1>(all_min)) {
      if (tw + get<0>(all_min) <= y) {
        uf.unite(i, get<2>(all_min));
      }
    } else {
      if (tw + get<0>(all_min2) <= y) {
        uf.unite(i, get<2>(all_min2));
      }
    }
  }
  vector<map<int, int>> vmp(n);
  REP(i, n) {
    int r = uf.find(i);
    vmp[r][v[i].second]++;
  }

  Mod ans = 1;
  for (auto mp : vmp) {
    if (mp.size() == 0)
      continue;
    int sum = 0;
    Mod tmp = 1;
    for (auto i : mp)
      sum += i.second;
    for (auto i : mp) {
      tmp *= comb<mod>(sum, i.second);
      sum -= i.second;
    }
    ans *= tmp;
  }
  cout << int(ans) << endl;
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1e9 + 7;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <class T> istream &operator>>(istream &is, vector<T> &v) {
  for (auto &i : v)
    is >> i;
  return is;
}
template <class T> ostream &operator<<(ostream &os, vector<T> &v) {
  const string delimiter = "\n";
  REP(i, v.size()) {
    os << v[i];
    if (i != v.size() - 1)
      os << delimiter;
  }
  return os;
}
/*--------------------template--------------------*/

const int INF = 1e9 + 1;

struct UnionFind {
  vector<int> par;
  UnionFind(int n) : par(n, -1) {}
  int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (par[y] < par[x])
      swap(x, y);
    if (par[x] == par[y])
      par[x]--;
    par[y] = x;
    if (find(x) != find(y))
      par[find(y)] = x;
  }
  int count() {
    int cnt = 0;
    REP(i, par.size()) if (par[i] < 0) cnt++;
    return cnt;
  }
  bool same(int x, int y) { return find(x) == find(y); }
};

template <int M> class Cyclic {
  using ll = long long;
  int n;
  static ll inv(ll a, ll p) {
    return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
  }

public:
  Cyclic() : n(0) { ; }
  Cyclic(int m) : n(m) {
    if (n >= M)
      n %= M;
    else if (n < 0)
      n = (n % M + M) % M;
  }
  operator int() const { return n; }
  bool operator==(const Cyclic &a) const { return n == a.n; }
  Cyclic operator+=(const Cyclic &a) {
    n += a.n;
    if (n >= M)
      n -= M;
    return *this;
  }
  Cyclic operator-=(const Cyclic &a) {
    n -= a.n;
    if (n < 0)
      n += M;
    return *this;
  }
  Cyclic operator*=(const Cyclic &a) {
    n = (ll(n) * a.n) % M;
    return *this;
  }
  Cyclic operator+(const Cyclic &a) const {
    Cyclic res = *this;
    return res += a;
  }
  Cyclic operator-(const Cyclic &a) const {
    Cyclic res = *this;
    return res -= a;
  }
  Cyclic operator*(const Cyclic &a) const {
    Cyclic res = *this;
    return res *= a;
  }
  Cyclic operator/(const Cyclic &a) const {
    return *this * Cyclic<M>(inv(a, M));
  }
  Cyclic operator^(int n) const {
    if (n == 0)
      return Cyclic(1);
    const Cyclic a = *this;
    Cyclic res = (a * a) ^ (n / 2);
    return n % 2 ? res * a : res;
  }
};

template <int M> Cyclic<M> fact(int n, bool sw = true) {
  static vector<Cyclic<M>> v1 = {1}, v2 = {1};
  if (n >= (int)v1.size()) {
    const int from = v1.size(), to = n + 1024;
    v1.reserve(to);
    v2.reserve(to);
    for (int i = from; i < to; ++i) {
      v1.push_back(v1.back() * Cyclic<M>(i));
      v2.push_back(v2.back() / Cyclic<M>(i));
    }
  }
  return sw ? v1[n] : v2[n];
}

template <int M> Cyclic<M> comb(int a, int b) {
  return fact<M>(a, true) * fact<M>(b, false) * fact<M>(a - b, false);
}

const int mod = 1000000007;
using Mod = Cyclic<mod>;

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  int n, x, y;
  cin >> n >> x >> y;
  vector<pii> v;
  REP(i, n) {
    int a, b;
    cin >> a >> b;
    v.emplace_back(b, a);
  }
  sort(ALL(v));
  map<int, pii> color_min; // color, <weight, index>
  tuple<int, int, int> all_min(INF, -1, -1),
      all_min2(INF, -1, -1); // weight, color, index
  REP(i, n) {
    int tw = v[i].first, tc = v[i].second;
    if (color_min.count(tc) == 0)
      color_min[tc] = pii(tw, i);

    if (get<0>(all_min) > tw) {
      if (tc != get<1>(all_min2))
        all_min2 = all_min;
      all_min = make_tuple(tw, tc, i);
    } else if (get<0>(all_min2) > tw && get<1>(all_min) != tc) {
      all_min2 = make_tuple(tw, tc, i);
    }
  }
  assert(get<1>(all_min) != get<1>(all_min2));
  UnionFind uf(n);
  REP(i, n) {
    int tw = v[i].first, tc = v[i].second;
    if (color_min[tc].second != i && tw + color_min[tc].first <= x) {
      uf.unite(i, color_min[tc].second);
    }

    if (tc != get<1>(all_min)) {
      if (tw + get<0>(all_min) <= y) {
        uf.unite(i, get<2>(all_min));
      }
    } else {
      if (tw + get<0>(all_min2) <= y) {
        uf.unite(i, get<2>(all_min2));
      }
    }
  }
  vector<map<int, int>> vmp(n);
  REP(i, n) {
    int r = uf.find(i);
    vmp[r][v[i].second]++;
  }

  Mod ans = 1;
  for (auto mp : vmp) {
    if (mp.size() == 0)
      continue;
    int sum = 0;
    Mod tmp = 1;
    for (auto i : mp)
      sum += i.second;
    for (auto i : mp) {
      tmp *= comb<mod>(sum, i.second);
      sum -= i.second;
    }
    ans *= tmp;
  }
  cout << int(ans) << endl;
  return 0;
}