Problem:
Problem G: Combine Two Elements
Problem
$N$個の非負整数のペア$(a_i, b_i)$と非負整数$A$, $B$ が与えられる。
以下のいずれかの操作をできるだけたくさん行いたい。
$|a_i - b_i| \leq A$ または $B \leq |a_i - b_i| \leq 2A$を満たす要素$i$を取り出し、削除する
$|(a_i + a_j) - (b_i + b_j)| \leq A$ または $B \leq |(a_i + a_j) - (b_i + b_j)| \leq 2A$ を満たす要素$i$と要素$j$ ($i \neq j$)の組を取り出し、削除する
最大の操作回数を求めよ。
Input
入力は以下の形式で与えられる。
$N$ $A$ $B$
$a_1$ $b_1$
$a_2$ $b_2$
...
$a_N$ $b_N$
入力はすべて整数で与えられる。
1行目に$N$,$A$,$B$が空白区切りで与えられる。
2行目以降の$N$行に$i$個目のペア$a_i$と$b_i$($1 \leq i \leq N$)が空白区切りで与えられる。
Constraints
入力は以下の条件を満たす。
$1 \leq N \leq 800 $
$0 \leq A, B \leq 10^5 $
$0 \leq a_i, b_i \leq 10^5$
$A \leq B$ かつ $B \leq 2A$
Output
最大の操作回数を1行に出力せよ。
Sample Input 1
5 3 5
7 2
13 1
1 1
2 9
2 4
Sample Output 1
4
(7,2)を選んで削除する。
(1,1)を選んで削除する。
(2,4)を選んで削除する。
(13, 1)と(2, 9)を選んで削除する。
以上のように操作すると４回操作することができ、これが最大となる。
Sample Input 2
10 7 12
34 70
36 0
12 50
76 46
33 45
61 21
0 1
24 3
98 41
23 84
Sample Output 2
5

Submitted solutions:

code_snippet: // #include <algorithm>
#include <cassert>
#include <cmath>
#include <ctime>
#include <iostream>
#include <utility>
#include <vector>

template <int M>
struct MInt {
  unsigned int val;
  MInt(): val(0) {}
  MInt(long long x) : val(x >= 0 ? x % M : x % M + M) {}
  static constexpr int get_mod() { return M; }
  static void set_mod(int divisor) { assert(divisor == M); }
  static void init(int x = 10000000) { inv(x, true); fact(x); fact_inv(x); }
  static MInt inv(int x, bool init = false) {
    // assert(0 <= x && x < M && std::__gcd(x, M) == 1);
    static std::vector<MInt> inverse{0, 1};
    int prev = inverse.size();
    if (init && x >= prev) {
      // "x!" and "M" must be disjoint.
      inverse.resize(x + 1);
      for (int i = prev; i <= x; ++i) inverse[i] = -inverse[M % i] * (M / i);
    }
    if (x < inverse.size()) return inverse[x];
    unsigned int a = x, b = M; int u = 1, v = 0;
    while (b) {
      unsigned int q = a / b;
      std::swap(a -= q * b, b);
      std::swap(u -= q * v, v);
    }
    return u;
  }
  static MInt fact(int x) {
    static std::vector<MInt> f{1};
    int prev = f.size();
    if (x >= prev) {
      f.resize(x + 1);
      for (int i = prev; i <= x; ++i) f[i] = f[i - 1] * i;
    }
    return f[x];
  }
  static MInt fact_inv(int x) {
    static std::vector<MInt> finv{1};
    int prev = finv.size();
    if (x >= prev) {
      finv.resize(x + 1);
      finv[x] = inv(fact(x).val);
      for (int i = x; i > prev; --i) finv[i - 1] = finv[i] * i;
    }
    return finv[x];
  }
  static MInt nCk(int n, int k) {
    if (n < 0 || n < k || k < 0) return 0;
    if (n - k > k) k = n - k;
    return fact(n) * fact_inv(k) * fact_inv(n - k);
  }
  static MInt nPk(int n, int k) { return n < 0 || n < k || k < 0 ? 0 : fact(n) * fact_inv(n - k); }
  static MInt nHk(int n, int k) { return n < 0 || k < 0 ? 0 : (k == 0 ? 1 : nCk(n + k - 1, k)); }
  static MInt large_nCk(long long n, int k) {
    if (n < 0 || n < k || k < 0) return 0;
    inv(k, true);
    MInt res = 1;
    for (int i = 1; i <= k; ++i) res *= inv(i) * n--;
    return res;
  }
  MInt pow(long long exponent) const {
    MInt tmp = *this, res = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }
  MInt &operator+=(const MInt &x) { if((val += x.val) >= M) val -= M; return *this; }
  MInt &operator-=(const MInt &x) { if((val += M - x.val) >= M) val -= M; return *this; }
  MInt &operator*=(const MInt &x) { val = static_cast<unsigned long long>(val) * x.val % M; return *this; }
  MInt &operator/=(const MInt &x) { return *this *= inv(x.val); }
  bool operator==(const MInt &x) const { return val == x.val; }
  bool operator!=(const MInt &x) const { return val != x.val; }
  bool operator<(const MInt &x) const { return val < x.val; }
  bool operator<=(const MInt &x) const { return val <= x.val; }
  bool operator>(const MInt &x) const { return val > x.val; }
  bool operator>=(const MInt &x) const { return val >= x.val; }
  MInt &operator++() { if (++val == M) val = 0; return *this; }
  MInt operator++(int) { MInt res = *this; ++*this; return res; }
  MInt &operator--() { val = (val == 0 ? M : val) - 1; return *this; }
  MInt operator--(int) { MInt res = *this; --*this; return res; }
  MInt operator+() const { return *this; }
  MInt operator-() const { return MInt(val ? M - val : 0); }
  MInt operator+(const MInt &x) const { return MInt(*this) += x; }
  MInt operator-(const MInt &x) const { return MInt(*this) -= x; }
  MInt operator*(const MInt &x) const { return MInt(*this) *= x; }
  MInt operator/(const MInt &x) const { return MInt(*this) /= x; }
  friend std::ostream &operator<<(std::ostream &os, const MInt &x) { return os << x.val; }
  friend std::istream &operator>>(std::istream &is, MInt &x) { long long val; is >> val; x = MInt(val); return is; }
};
namespace std { template <int M> MInt<M> abs(const MInt<M> &x) { return x; } }

template <typename T>
struct Matrix {
  Matrix(int m, int n, T val = 0) : dat(m, std::vector<T>(n, val)) {}

  int height() const { return dat.size(); }

  int width() const { return dat.front().size(); }

  Matrix pow(long long exponent) const {
    int n = height();
    Matrix<T> tmp = *this, res(n, n, 0);
    for (int i = 0; i < n; ++i) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const std::vector<T> &operator[](const int idx) const { return dat[idx]; }
  inline std::vector<T> &operator[](const int idx) { return dat[idx]; }

  Matrix &operator=(const Matrix &x) {
    int m = x.height(), n = x.width();
    dat.resize(m, std::vector<T>(n));
    for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) dat[i][j] = x[i][j];
    return *this;
  }

  Matrix &operator+=(const Matrix &x) {
    int m = height(), n = width();
    for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) dat[i][j] += x[i][j];
    return *this;
  }

  Matrix &operator-=(const Matrix &x) {
    int m = height(), n = width();
    for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) dat[i][j] -= x[i][j];
    return *this;
  }

  Matrix &operator*=(const Matrix &x) {
    int m = height(), n = x.width(), l = width();
    std::vector<std::vector<T>> res(m, std::vector<T>(n, 0));
    for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) {
      for (int k = 0; k < l; ++k) res[i][j] += dat[i][k] * x[k][j];
    }
    std::swap(dat, res);
    return *this;
  }

  Matrix operator+(const Matrix &x) const { return Matrix(*this) += x; }

  Matrix operator-(const Matrix &x) const { return Matrix(*this) -= x; }

  Matrix operator*(const Matrix &x) const { return Matrix(*this) *= x; }

private:
  std::vector<std::vector<T>> dat;
};

template <typename T>
int gauss_jordan(Matrix<T> &mat, const T EPS = 1e-8, bool is_extended = false) {
  int m = mat.height(), n = mat.width(), rank = 0;
  for (int col = 0; col < n; ++col) {
    if (is_extended && col == n - 1) break;
    int pivot = -1;
    T mx = EPS;
    for (int row = rank; row < m; ++row) {
      if (std::abs(mat[row][col]) > mx) {
        pivot = row;
        mx = std::abs(mat[row][col]);
      }
    }
    if (pivot == -1) continue;
    std::swap(mat[rank], mat[pivot]);
    T tmp = mat[rank][col];
    for (int col2 = 0; col2 < n; ++col2) mat[rank][col2] /= tmp;
    for (int row = 0; row < m; ++row) {
      if (row != rank && std::abs(mat[row][col]) > EPS) {
        tmp = mat[row][col];
        for (int col2 = 0; col2 < n; ++col2) mat[row][col2] -= mat[rank][col2] * tmp;
      }
    }
    ++rank;
  }
  return rank;
}

struct Xor128 {
  int rand() {
    unsigned int t = x ^ (x << 11);
    x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return static_cast<int>(w);
  }
  int rand(int ub) {
    int res = rand() % ub;
    return res < 0 ? res + ub : res;
  }
  int rand(int lb, int ub) { return lb + rand(ub - lb); }
  long long randll() {
    unsigned long long res = static_cast<unsigned long long>(rand()) << 32;
    return static_cast<long long>(res | rand());
  }
  long long randll(long long ub) {
    long long res = randll() % ub;
    return res < 0 ? res + ub : res;
  }
  long long randll(long long lb, long long ub) { return lb + randll(ub - lb); }
private:
  unsigned int x = 123456789, y = 362436069, z = 521288629, w = static_cast<unsigned int>(std::time(nullptr));
} xor128;

int maximum_matching(const std::vector<std::vector<int>> &graph) {
  constexpr int P = 1000000007;
  using ModInt = MInt<P>;
  ModInt::set_mod(P);
  const int n = graph.size();
  Matrix<ModInt> tutte_matrix(n, n, 0);
  for (int i = 0; i < n; ++i) {
    for (const int j : graph[i]) {
      if (j > i) {
        const ModInt x = xor128.rand(1, P);
        tutte_matrix[i][j] = x;
        tutte_matrix[j][i] = -x;
      }
    }
  }
  return gauss_jordan(tutte_matrix, ModInt(0)) / 2;
}

int main() {
  int n, A, B;
  std::cin >> n >> A >> B;
  int ans = 0;
  std::vector<int> a, b;
  while (n--) {
    int a_i, b_i;
    std::cin >> a_i >> b_i;
    const int x = std::abs(a_i - b_i);
    if (x <= A || (B <= x && x <= 2 * A)) {
      ++ans;
    } else {
      a.emplace_back(a_i);
      b.emplace_back(b_i);
    }
  }
  n = a.size();
  if (n > 0) {
    std::vector<std::vector<int>> graph(n);
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        const int x = std::abs((a[i] + a[j]) - (b[i] + b[j]));
        if (x <= A || (B <= x && x <= 2 * A)) {
          graph[i].emplace_back(j);
          graph[j].emplace_back(i);
        }
      }
    }
    ans += maximum_matching(graph);
  }
  std::cout << ans << '\n';
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 5328
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < n; i++)
#define rep2(i, x, n) for(int i = x; i <= n; i++)
#define rep3(i, x, n) for(int i = x; i >= n; i--)
#define elif else if
#define sp(x) fixed << setprecision(x)
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
const ll MOD = 1e9+7;
//const ll MOD = 998244353;
const int inf = (1<<30)-1;
const ll INF = (1LL<<60)-1;
const ld EPS = 1e-10;
template<typename T> bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;};
template<typename T> bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;};

template<typename T>
struct Max_Flow{
    struct edge{
        int to; T cap; int rev;
        edge(int to, T cap, int rev) : to(to), cap(cap), rev(rev) {}
    };

    vector<vector<edge>> es;
    vector<bool> used;
    const T INF_T;

    Max_Flow(int n) : INF_T(numeric_limits<T>::max()){
        es.resize(n), used.resize(n);
    }

    void add_edge(int from, int to, T cap, bool directed = true){
        es[from].eb(to, cap, sz(es[to]));
        es[to].eb(from, directed? 0 : cap, sz(es[from])-1);
    }

    T dfs(int now, int t, T flow){
        if(now == t) return flow;
        used[now] = true;
        for(auto &e: es[now]){
            if(!used[e.to] && e.cap > 0){
                T f = dfs(e.to, t, min(flow, e.cap));
                if(f > 0){
                    e.cap -= f;
                    es[e.to][e.rev].cap += f;
                    return f;
                }
            }
        }
        return 0;
    }

    T max_flow(int s, int t){
        T flow = 0;
        for(;;){
            fill(all(used), false);
            T f = dfs(s, t, INF_T);
            if(f == 0) return flow;
            flow += f;
        }
    }
};

int main(){
    int N, A, B;
    cin >> N >> A >> B;
    int a[N], b[N];
    bool used[N];
    fill(used, used+N, false);
    int ans = 0;
    rep(i, N){
        cin >> a[i] >> b[i];
        a[i] -= b[i];
        int tmp = abs(a[i]);
        if(tmp <= A || (B <= tmp && tmp <= 2*A)) ans++, used[i] = true;
    }
    Max_Flow<int> G(2*N+2);
    int s = 2*N, t = 2*N+1;
    rep(i, N) G.add_edge(s, i, 1), G.add_edge(N+i, t, 1);
    rep(i, N){
        if(used[i] || a[i] < 0) continue;
        rep(j, N){
            if(used[j]) continue;
            int tmp = abs(a[i]+a[j]);
            if(tmp <= A || (B <= tmp && tmp <= 2*A)) G.add_edge(i, N+j, 1);
        }
    }
    cout << ans+G.max_flow(s, t) << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 4296
final_rank: 2

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
template <typename T> using posteriority_queue = priority_queue<T, vector<T>, greater<T> >;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
// const int dy[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
template <typename T> void unique(vector<T> &a) { a.erase(unique(ALL(a)), a.end()); }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <typename T>
struct Matrix {
  Matrix(int m, int n, T val = 0) : dat(m, vector<T>(n, val)) {}

  int height() const { return dat.size(); }

  int width() const { return dat.front().size(); }

  Matrix pow(ll exponent) {
    int n = height();
    Matrix<T> tmp = *this, res(n, n, 0);
    REP(i, n) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const vector<T> &operator[](const int idx) const { return dat[idx]; }
  inline vector<T> &operator[](const int idx) { return dat[idx]; }

  Matrix &operator=(const Matrix &x) {
    int m = x.height(), n = x.width();
    dat.resize(m, vector<T>(n));
    REP(i, m) REP(j, n) dat[i][j] = x[i][j];
    return *this;
  }

  Matrix &operator+=(const Matrix &x) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] += x[i][j];
    return *this;
  }

  Matrix &operator-=(const Matrix &x) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] -= x[i][j];
    return *this;
  }

  Matrix &operator*=(const Matrix &x) {
    int m = height(), n = x.width(), l = width();
    vector<vector<T> > res(m, vector<T>(n, 0));
    REP(i, m) REP(j, n) {
      REP(k, l) res[i][j] += dat[i][k] * x[k][j];
    }
    swap(dat, res);
    return *this;
  }

  Matrix operator+(const Matrix &x) const { return Matrix(*this) += x; }

  Matrix operator-(const Matrix &x) const { return Matrix(*this) -= x; }

  Matrix operator*(const Matrix &x) const { return Matrix(*this) *= x; }

private:
  vector<vector<T> > dat;
};

template <typename T>
int gauss_jordan(Matrix<T> &mat, bool is_extended = false) {
  int m = mat.height(), n = mat.width(), rank = 0;
  REP(col, n) {
    if (is_extended && col == n - 1) break;
    int pivot = -1;
    T mx = EPS;
    FOR(row, rank, m) {
      if (abs(mat[row][col]) > mx) {
        pivot = row;
        mx = abs(mat[row][col]);
      }
    }
    if (pivot == -1) continue;
    swap(mat[rank], mat[pivot]);
    T tmp = mat[rank][col];
    REP(col2, n) mat[rank][col2] /= tmp;
    REP(row, m) {
      if (row != rank && abs(mat[row][col]) > EPS) {
        tmp = mat[row][col];
        REP(col2, n) mat[row][col2] -= mat[rank][col2] * tmp;
      }
    }
    ++rank;
  }
  return rank;
}

struct Xor128 {
  int rand() {
    unsigned t = x ^ (x << 11);
    x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return static_cast<int>(w);
  }
  int rand(int ub) {
    int res = rand() % ub;
    return (res < 0 ? res + ub : res);
  }
  int rand(int lb, int ub) { return lb + rand(ub - lb); }
  ll randll() {
    unsigned long long res = static_cast<unsigned long long>(rand()) << 32;
    return static_cast<ll>(res | rand());
  }
  ll randll(ll ub) {
    ll res = randll() % ub;
    return (res < 0 ? res + ub : res);
  }
  ll randll(ll lb, ll ub) { return lb + rand(ub - lb); }
private:
  unsigned x = 123456789, y = 362436069, z = 521288629, w = static_cast<unsigned>(time(nullptr));
} xor128;

int tutte_theorem(const vector<vector<int> > &graph) {
  int n = graph.size();
  Matrix<double> mat(n, n, 0);
  REP(i, n) {
    for (int e : graph[i]) {
      if (e > i) {
        double x = 0;
        while (x < EPS) {
          int den = xor128.rand();
          if (den > EPS) x = 1.0 * xor128.rand() / den;
        }
        mat[i][e] = x;
        mat[e][i] = -x;
      }
    }
  }
  return gauss_jordan(mat) / 2;
}

int main() {
  int n, A, B; cin >> n >> A >> B;
  int ans = 0;
  vector<int> a, b;
  while (n--) {
    int ai, bi; cin >> ai >> bi;
    int val = abs(ai - bi);
    if (val <= A || (B <= val && val <= 2 * A)) {
      ++ans;
    } else {
      a.emplace_back(ai);
      b.emplace_back(bi);
    }
  }
  n = a.size();
  if (n > 0) {
    vector<vector<int> > graph(n);
    REP(i, n) FOR(j, i + 1, n) {
      int val = abs((a[i] + a[j]) - (b[i] + b[j]));
      if (val <= A || (B <= val && val <= 2 * A)) {
        graph[i].emplace_back(j);
        graph[j].emplace_back(i);
      }
    }
    ans += tutte_theorem(graph);
  }
  cout << ans << '\n';
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 7556
final_rank: 14

code_snippet: #include <cmath>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)

const double EPS = 1e-8;

struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cerr << fixed << setprecision(10);
  }
} iosetup;
/*-------------------------------------------------*/
template <typename T>
struct Matrix {
  Matrix(int m, int n, T val = 0) : dat(m, vector<T>(n, val)) {}

  int height() const { return dat.size(); }

  int width() const { return dat.front().size(); }

  Matrix pow(long long exponent) {
    int n = height();
    Matrix<T> tmp = *this, res(n, n, 0);
    REP(i, n) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const vector<T> &operator[](const int idx) const { return dat[idx]; }
  inline vector<T> &operator[](const int idx) { return dat[idx]; }

  Matrix &operator=(const Matrix &rhs) {
    int m = rhs.height(), n = rhs.width();
    dat.resize(m, vector<T>(n));
    REP(i, m) REP(j, n) dat[i][j] = rhs[i][j];
    return *this;
  }

  Matrix &operator+=(const Matrix &rhs) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] += rhs[i][j];
    return *this;
  }

  Matrix &operator-=(const Matrix &rhs) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] -= rhs[i][j];
    return *this;
  }

  Matrix &operator*=(const Matrix &rhs) {
    int m = height(), n = rhs.width(), l = width();
    vector<vector<T> > res(m, vector<T>(n, 0));
    REP(i, m) REP(j, n) {
      REP(k, l) res[i][j] += dat[i][k] * rhs[k][j];
    }
    swap(dat, res);
    return *this;
  }

  Matrix operator+(const Matrix &rhs) const { return Matrix(*this) += rhs; }

  Matrix operator-(const Matrix &rhs) const { return Matrix(*this) -= rhs; }

  Matrix operator*(const Matrix &rhs) const { return Matrix(*this) *= rhs; }

private:
  vector<vector<T> > dat;
};

template <typename T>
int gauss_jordan(Matrix<T> &mat, bool is_extended = false) {
  int m = mat.height(), n = mat.width(), rank = 0;
  REP(col, n) {
    if (is_extended && col == n - 1) break;
    int pivot = -1;
    T mx = EPS;
    FOR(row, rank, m) {
      if (abs(mat[row][col]) > mx) {
        pivot = row;
        mx = abs(mat[row][col]);
      }
    }
    if (pivot == -1) continue;
    swap(mat[rank], mat[pivot]);
    T tmp = mat[rank][col];
    REP(col2, n) mat[rank][col2] /= tmp;
    REP(row, m) if (row != rank && abs(mat[row][col]) > EPS) {
      tmp = mat[row][col];
      REP(col2, n) mat[row][col2] -= mat[rank][col2] * tmp;
    }
    ++rank;
  }
  return rank;
}

struct Xor128 {
  int rand() {
    unsigned t = x ^ (x << 11);
    x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return static_cast<int>(w);
  }
  int rand(int ub) {
    int res = rand() % ub;
    return (res < 0 ? res + ub : res);
  }
  int rand(int lb, int ub) { return lb + rand(ub - lb); }
  long long randll() {
    unsigned long long res = static_cast<unsigned long long>(rand()) << 32;
    return static_cast<long long>(res | rand());
  }
  long long randll(long long ub) {
    long long res = randll() % ub;
    return (res < 0 ? res + ub : res);
  }
  long long randll(long long lb, long long ub) { return lb + rand(ub - lb); }
private:
  unsigned x = 123456789, y = 362436069, z = 521288629, w = static_cast<unsigned>(time(nullptr));
} xor128;

int matching(const vector<vector<int> > &graph) {
  int n = graph.size();
  Matrix<double> mat(n, n, 0);
  REP(i, n) {
    for (int e : graph[i]) if (e > i) {
      double x = 0;
      while (x < EPS) {
        int den = xor128.rand();
        if (den > EPS) x = static_cast<double>(xor128.rand()) / den;
      }
      mat[i][e] = x;
      mat[e][i] = -x;
    }
  }
  return gauss_jordan(mat) / 2;
}

int main() {
  int n, A, B; cin >> n >> A >> B;
  int ans = 0;
  vector<int> a, b;
  while (n--) {
    int ai, bi; cin >> ai >> bi;
    int val = abs(ai - bi);
    if (val <= A || (B <= val && val <= 2 * A)) {
      ++ans;
    } else {
      a.emplace_back(ai);
      b.emplace_back(bi);
    }
  }
  n = a.size();
  if (n > 0) {
    vector<vector<int> > graph(n);
    REP(i, n) FOR(j, i + 1, n) {
      int val = abs((a[i] + a[j]) - (b[i] + b[j]));
      if (val <= A || (B <= val && val <= 2 * A)) {
        graph[i].emplace_back(j);
        graph[j].emplace_back(i);
      }
    }
    ans += matching(graph);
  }
  cout << ans << '\n';
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 7532
final_rank: 13

code_snippet: #include <cmath>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)

const double EPS = 1e-8;

struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cerr << fixed << setprecision(10);
  }
} iosetup;
/*-------------------------------------------------*/
template <typename T>
struct Matrix {
  Matrix(int m, int n, T val = 0) : dat(m, vector<T>(n, val)) {}

  int height() const { return dat.size(); }

  int width() const { return dat.front().size(); }

  Matrix pow(long long exponent) {
    int n = height();
    Matrix<T> tmp = *this, res(n, n, 0);
    REP(i, n) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const vector<T> &operator[](const int idx) const { return dat[idx]; }
  inline vector<T> &operator[](const int idx) { return dat[idx]; }

  Matrix &operator=(const Matrix &rhs) {
    int m = rhs.height(), n = rhs.width();
    dat.resize(m, vector<T>(n));
    REP(i, m) REP(j, n) dat[i][j] = rhs[i][j];
    return *this;
  }

  Matrix &operator+=(const Matrix &rhs) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] += rhs[i][j];
    return *this;
  }

  Matrix &operator-=(const Matrix &rhs) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] -= rhs[i][j];
    return *this;
  }

  Matrix &operator*=(const Matrix &rhs) {
    int m = height(), n = rhs.width(), l = width();
    vector<vector<T> > res(m, vector<T>(n, 0));
    REP(i, m) REP(j, n) {
      REP(k, l) res[i][j] += dat[i][k] * rhs[k][j];
    }
    swap(dat, res);
    return *this;
  }

  Matrix operator+(const Matrix &rhs) const { return Matrix(*this) += rhs; }

  Matrix operator-(const Matrix &rhs) const { return Matrix(*this) -= rhs; }

  Matrix operator*(const Matrix &rhs) const { return Matrix(*this) *= rhs; }

private:
  vector<vector<T> > dat;
};

template <typename T>
int gauss_jordan(Matrix<T> &mat, bool is_extended = false) {
  int m = mat.height(), n = mat.width(), rank = 0;
  REP(col, n) {
    if (is_extended && col == n - 1) break;
    int pivot = -1;
    T mx = EPS;
    FOR(row, rank, m) {
      if (abs(mat[row][col]) > mx) {
        pivot = row;
        mx = abs(mat[row][col]);
      }
    }
    if (pivot == -1) continue;
    swap(mat[rank], mat[pivot]);
    T tmp = mat[rank][col];
    REP(col2, n) mat[rank][col2] /= tmp;
    REP(row, m) if (row != rank && abs(mat[row][col]) > EPS) {
      tmp = mat[row][col];
      REP(col2, n) mat[row][col2] -= mat[rank][col2] * tmp;
    }
    ++rank;
  }
  return rank;
}

struct Xor128 {
  int rand() {
    unsigned t = x ^ (x << 11);
    x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return static_cast<int>(w);
  }
  int rand(int ub) {
    int res = rand() % ub;
    return (res < 0 ? res + ub : res);
  }
  int rand(int lb, int ub) { return lb + rand(ub - lb); }
  long long randll() {
    unsigned long long res = static_cast<unsigned long long>(rand()) << 32;
    return static_cast<long long>(res | rand());
  }
  long long randll(long long ub) {
    long long res = randll() % ub;
    return (res < 0 ? res + ub : res);
  }
  long long randll(long long lb, long long ub) { return lb + rand(ub - lb); }
private:
  unsigned x = 123456789, y = 362436069, z = 521288629, w = static_cast<unsigned>(time(nullptr));
} xor128;

int matching(const vector<vector<int> > &graph) {
  int n = graph.size();
  Matrix<double> mat(n, n, 0);
  REP(i, n) {
    for (int e : graph[i]) if (e > i) {
      double x = static_cast<double>(xor128.rand()) / xor128.rand();
      mat[i][e] = x;
      mat[e][i] = -x;
    }
  }
  return gauss_jordan(mat) / 2;
}

int main() {
  int n, A, B; cin >> n >> A >> B;
  int ans = 0;
  vector<int> a, b;
  while (n--) {
    int ai, bi; cin >> ai >> bi;
    int val = abs(ai - bi);
    if (val <= A || (B <= val && val <= 2 * A)) {
      ++ans;
    } else {
      a.emplace_back(ai);
      b.emplace_back(bi);
    }
  }
  n = a.size();
  if (n > 0) {
    vector<vector<int> > graph(n);
    REP(i, n) FOR(j, i + 1, n) {
      int val = abs((a[i] + a[j]) - (b[i] + b[j]));
      if (val <= A || (B <= val && val <= 2 * A)) {
        graph[i].emplace_back(j);
        graph[j].emplace_back(i);
      }
    }
    ans += matching(graph);
  }
  cout << ans << '\n';
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 7512
final_rank: 12

code_snippet: #include <cmath>
#include <ctime>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)

const double EPS = 1e-8;
/*-------------------------------------------------*/
template <typename T>
struct Matrix {
  Matrix(int m, int n, T val = 0) : dat(m, vector<T>(n, val)) {}

  int height() const { return dat.size(); }

  int width() const { return dat.front().size(); }

  Matrix pow(long long exponent) {
    int n = height();
    Matrix<T> tmp = *this, res(n, n, 0);
    REP(i, n) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const vector<T> &operator[](const int idx) const { return dat[idx]; }
  inline vector<T> &operator[](const int idx) { return dat[idx]; }

  Matrix &operator=(const Matrix &rhs) {
    int m = rhs.height(), n = rhs.width();
    dat.resize(m, vector<T>(n));
    REP(i, m) REP(j, n) dat[i][j] = rhs[i][j];
    return *this;
  }

  Matrix &operator+=(const Matrix &rhs) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] += rhs[i][j];
    return *this;
  }

  Matrix &operator-=(const Matrix &rhs) {
    int m = height(), n = width();
    REP(i, m) REP(j, n) dat[i][j] -= rhs[i][j];
    return *this;
  }

  Matrix &operator*=(const Matrix &rhs) {
    int m = height(), n = rhs.width(), l = width();
    vector<vector<T> > res(m, vector<T>(n, 0));
    REP(i, m) REP(j, n) {
      REP(k, l) res[i][j] += dat[i][k] * rhs[k][j];
    }
    swap(dat, res);
    return *this;
  }

  Matrix operator+(const Matrix &rhs) const { return Matrix(*this) += rhs; }

  Matrix operator-(const Matrix &rhs) const { return Matrix(*this) -= rhs; }

  Matrix operator*(const Matrix &rhs) const { return Matrix(*this) *= rhs; }

private:
  vector<vector<T> > dat;
};

template <typename T>
int gauss_jordan(Matrix<T> &mat, bool is_extended = false) {
  int m = mat.height(), n = mat.width(), rank = 0;
  REP(col, n) {
    if (is_extended && col == n - 1) break;
    int pivot = -1;
    T mx = EPS;
    FOR(row, rank, m) {
      if (abs(mat[row][col]) > mx) {
        pivot = row;
        mx = abs(mat[row][col]);
      }
    }
    if (pivot == -1) continue;
    swap(mat[rank], mat[pivot]);
    T tmp = mat[rank][col];
    REP(col2, n) mat[rank][col2] /= tmp;
    REP(row, m) if (row != rank && abs(mat[row][col]) > EPS) {
      tmp = mat[row][col];
      REP(col2, n) mat[row][col2] -= mat[rank][col2] * tmp;
    }
    ++rank;
  }
  return rank;
}

struct Xor128 {
  int rand() {
    unsigned t = x ^ (x << 11);
    x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return static_cast<int>(w);
  }
  int rand(int ub) {
    int res = rand() % ub;
    return (res < 0 ? res + ub : res);
  }
  int rand(int lb, int ub) { return lb + rand(ub - lb); }
  long long randll() {
    unsigned long long res = static_cast<unsigned long long>(rand()) << 32;
    return static_cast<long long>(res | rand());
  }
  long long randll(long long ub) {
    long long res = randll() % ub;
    return (res < 0 ? res + ub : res);
  }
  long long randll(long long lb, long long ub) { return lb + rand(ub - lb); }
private:
  unsigned x = 123456789, y = 362436069, z = 521288629, w = static_cast<unsigned>(time(nullptr));
} xor128;

template <typename T>
int matching(const vector<vector<T> > &graph) {
  int n = graph.size();
  Matrix<double> mat(n, n);
  REP(i, n) FOR(j, i + 1, n) if (graph[i][j] != 0) {
    double x = static_cast<double>(xor128.rand()) / xor128.rand();
    mat[i][j] = x;
    mat[j][i] = -x;
  }
  return gauss_jordan(mat) / 2;
}

int main() {
  cin.tie(0); ios::sync_with_stdio(false);
  // freopen("input.txt", "r", stdin);

  int n, A, B; cin >> n >> A >> B;
  int ans = 0;
  vector<int> a, b;
  while (n--) {
    int ai, bi; cin >> ai >> bi;
    int val = abs(ai - bi);
    if (val <= A || (B <= val && val <= 2 * A)) {
      ++ans;
    } else {
      a.emplace_back(ai);
      b.emplace_back(bi);
    }
  }
  n = a.size();
  if (n > 0) {
    vector<vector<int> > graph(n, vector<int>(n, 0));
    REP(i, n) FOR(j, i + 1, n) {
      int val = abs((a[i] + a[j]) - (b[i] + b[j]));
      if (val <= A || (B <= val && val <= 2 * A)) graph[i][j] = graph[j][i] = 1;
    }
    ans += matching(graph);
  }
  cout << ans << '\n';
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 9576
final_rank: 15

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef long double ld;
typedef complex<ld> Point;
const ld eps = 1e-2;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;

#include<cstring>
struct edge { int to, cap, rev; };
vector<edge> G[100000];
bool used[100000];
void add_edge(int from, int to, int cap) {
	G[from].push_back(edge{ to, cap, (int)G[to].size() });
	G[to].push_back(edge{ from, 0, (int)G[from].size() - 1 });
}
int dfs(int v, int t, int f) {
	if (v == t)return f;
	used[v] = true;
	for (int i = 0; i < (int)G[v].size(); i++) {
		edge &e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			int d = dfs(e.to, t, min(f, e.cap));
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s, int t) {
	int flow = 0;
	for (;;) {
		memset(used, 0, sizeof(used));
		int f = dfs(s, t, mod);
		if (f == 0)return flow;
		flow += f;
	}
}
vector<P> v[2];
int main() {
	int n, a, b; cin >> n >> a >> b;
	int cnt = 0;
	rep(i, n) {
		int x, y; cin >> x >> y;
		int z = abs(x - y);
		if (z <= a || (b <= z && z <= 2 * a))cnt++;
		else {
			if (x-y>0) {
				v[0].push_back({ x,y });
			}
			else {
				v[1].push_back({ x,y });
			}
		}
	}
	int m = v[0].size(); int len = v[1].size();
	int sta = m + len, goa = m + len + 1;
	rep(i, m)add_edge(sta, i, 1);
	rep(i, len)add_edge(i + m, goa, 1);
	rep(i, m) {
		rep(j, len) {
			int z = v[0][i].first - v[0][i].second + v[1][j].first - v[1][j].second;
			z = abs(z);
			if (z <= a || (b <= z && z <= 2 * a)) {
				add_edge(i, m + j,1);
			}
		}
	}
	int ans = cnt + max_flow(sta,goa);
	cout << ans << endl;
	//stop
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6732
final_rank: 9

code_snippet: #include <vector>
#include <cassert>
#include <set>
#include <queue>
#include <functional>
#include <algorithm>

struct edge {
  int to;
  int label;
};


::std::vector<::std::pair<int,int>> gabow_edmonds(const ::std::vector<::std::vector<int>>& gra){
  int N = gra.size();
  ::std::vector<::std::vector<edge>> g(N + 1);
  ::std::vector<::std::pair<int,int>> edges;
  {
    int cnt = N + 1;
    for(int i = 0;i < N;i++){
      for(auto to : gra[i]){
        if(i < to){
          g[to + 1].push_back({i + 1,cnt});
          g[i + 1].push_back({to + 1,cnt++});
          edges.push_back({i + 1, to + 1});
        }
      }
    }
  }
  ::std::vector<int> mate(N + 1 , 0);
  ::std::vector<int> label(N + 1 , -1);
  ::std::vector<int> first(N + 1 , 0);

  ::std::function<int(int)> eval_first = [&](int x){
    if(label[first[x]] < 0) return first[x];
    first[x] = eval_first(first[x]);
    return first[x];
  };

  ::std::function<void(int,int)> rematch = [&](int v,int w){
    int t = mate[v];
    mate[v] = w;
    if(mate[t] != v) return;
    if(label[v] <= N){
      mate[t] = label[v];
      rematch(label[v] , t);
    }
    else{
      int x = edges[label[v] - N + 1].first;
      int y = edges[label[v] - N + 1].second;
      rematch(x , y);
      rematch(y , x);
    }
  };

  ::std::function<void(int,int,int)> assignLabel = [&](int x, int y,int num){
    int r = eval_first(x);
    int s = eval_first(y);
    int join = 0;
    if(r == s) return;
    label[r] = -num;
    label[s] = -num;
    while(true){
      if(s != 0) ::std::swap(r , s);
      r = eval_first(label[mate[r]]);
      if(label[r] == -num){
        join = r;
        break;
      }
      label[r] = -num;
    }
    int v = first[x];
    while(v != join){
      label[v] = num;
      first[v] = join;
      v = first[label[mate[v]]];
    }
    v = first[y];
    while(v != join){
      label[v] = num;
      first[v] = join;
      v = first[label[mate[v]]];
    }
    return;
  };

  ::std::function<bool(int)> augment_check = [&](int u){
    first[u] = 0;
    label[u] = 0;
    ::std::queue<int> que;
    que.push(u);
    while(!que.empty()){
      int x = que.front();
      que.pop();
      for(auto e : g[x]){
        int y = e.to;
        if(mate[y] == 0 && y != u){
          mate[y] = x;
          rematch(x , y);
          return true;
        }
        else if(label[y] >= 0){
          assignLabel(x , y , e.label);
        }
        else if(label[mate[y]] < 0){
          label[mate[y]] = x;
          first[mate[y]] = y;
          que.push(mate[y]);
        }
      }
    }
    return false;
  };

  for(int i = 1;i <= N;i++){
    if(mate[i] != 0) continue;
    if(augment_check(i)){
      ::std::fill(label.begin() , label.end() , -1);
    }
  }

  ::std::vector<::std::pair<int,int>> ans;
  for(int i = 1;i <= N;i++){
    if(i < mate[i]){
      ans.push_back({i , mate[i]});
    }
  }
  return ans;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i,s,e) for(int (i) = (s);(i) <= (e);(i)++)

int main(){
  int N,A,B;
  cin >> N >> A >> B;
  vector<int> a(N),b(N);
  for(int i = 0;i < N;i++){
    cin >> a[i] >> b[i];
  }
  vector<vector<int>> g(N * 2);
  for(int i = 0;i < N;i++){
    int t = abs(a[i] - b[i]);
    if(t <= A || (B <= t && t <= 2 * A)){
      g[i].push_back(i + N);
      g[i + N].push_back(i);
    }
  }
  for(int i = 0;i < N;i++){
    for(int j = i + 1;j < N;j++){
      int t = abs(a[i] + a[j] - b[i] - b[j]);
      if(t <= A || (B <= t && t <= 2 * A)){
        g[i].push_back(j);
        g[j].push_back(i);
      }
    }
  }

  cout << gabow_edmonds(g).size() << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 16752
final_rank: 18

code_snippet: #include "bits/stdc++.h"
using namespace std;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
static const int INF = 0x3f3f3f3f; static const long long INFL = 0x3f3f3f3f3f3f3f3fLL;
typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pair<int, int> > vpii; typedef long long ll;
template<typename T, typename U> static void amin(T &x, U y) { if (y < x) x = y; }
template<typename T, typename U> static void amax(T &x, U y) { if (x < y) x = y; }
#define each(it,o) for(auto it = (o).begin(); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#ifdef _DEBUG
#include "dump.hpp"
#else
#define dump(...)
#endif

typedef int Weight;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src_, int dst_, Weight weight_) : src(src_), dst(dst_), weight(weight_) { }
	Edge() {};
};
typedef vector<Edge> Edges;
struct MaxWeightMatching {
	int nEdge, nVertex;
	Weight maxWeight;
	vi endPoint, mate, label, labelEdge,
		inBlossom, blossomParent, blossomBase,
		bestEdge, unusedBlossoms, allowEdge,
		blossomBestEdgesUsed,
		sVerteices;
	vector<Weight> dualVar;
	vector<vi> neighbEnd, blossomChilds, blossomEdges,
		blossomBestEdges;
	Edges edges;
	bool maxCardinality;

	Weight slack(int k) {
		Edge &e = edges[k];
		return dualVar[e.src] + dualVar[e.dst] - 2 * e.weight;
	}
	struct BlossomLeaves {
		int b;
		MaxWeightMatching *mw;
		enum { INITAL, END, NEXT, THIRD } state;
		vi::const_iterator iter, endi;
		BlossomLeaves *bl;
		BlossomLeaves(MaxWeightMatching *mw_, int b_) :
			mw(mw_), b(b_), state(INITAL), bl(NULL) {}
		bool next(int &r) {
			int t;
			switch (state) {
			case INITAL:
				if (b < mw->nVertex) {
					r = b;
					state = END;
					return true;
				}
				else {
					iter = mw->blossomChilds[b].begin();
					endi = mw->blossomChilds[b].end();
					state = NEXT;
					return next(r);
				}
			case END:
				return false;
			case NEXT:
				if (iter == endi)
					return false;
				t = *iter;
				++iter;
				if (t < mw->nVertex) {
					r = t;
					return true;
				}
				else {
					bl = new BlossomLeaves(mw, t);
					state = THIRD;
					return next(r);
				}
			case THIRD:
				if (!bl->next(t)) {
					state = NEXT;
					delete bl; bl = NULL;
					return next(r);
				}
				else {
					r = t;
					return true;
				}
			}
			return false;
		}
	};
	void assignLabel(int w, int t, int p) {
		int b = inBlossom[w];
		label[w] = label[b] = t;
		labelEdge[w] = labelEdge[b] = p;
		bestEdge[w] = bestEdge[b] = -1;
		if (t == 1) {
			BlossomLeaves bl(this, b);
			for (int r; bl.next(r); ) sVerteices.push_back(r);
		}
		else if (t == 2) {
			int base = blossomBase[b];
			assignLabel(endPoint[mate[base]], 1, mate[base] ^ 1);
		}
	}
	int scanBlossom(int v, int w) {
		vi path;
		int base = -1;
		while (v != -1) {
			int b = inBlossom[v];
			if (label[b] & 4) {
				base = blossomBase[b];
				break;
			}
			path.push_back(b);
			label[b] = 5;
			if (labelEdge[b] == -1) {
				v = -1;
			}
			else {
				v = endPoint[labelEdge[b]];
				b = inBlossom[v];
				v = endPoint[labelEdge[b]];
			}
			if (w != -1)
				swap(v, w);
		}
		each(it, path)
			label[*it] = 1;
		return base;
	}
	void addBlossom(int base, int k) {
		Edge &e = edges[k];
		int bb = inBlossom[base],
			bv = inBlossom[e.src],
			bw = inBlossom[e.dst];
		int b = unusedBlossoms.back(); unusedBlossoms.pop_back();
		blossomBase[b] = base;
		blossomParent[b] = -1;
		blossomParent[bb] = b;
		blossomChilds[b].clear();
		blossomEdges[b].clear();
		vi &bChilds = blossomChilds[b];
		vi &bEdges = blossomEdges[b];
		while (bv != bb) {
			blossomParent[bv] = b;
			bChilds.push_back(bv);
			bEdges.push_back(labelEdge[bv]);
			bv = inBlossom[endPoint[labelEdge[bv]]];
		}
		bChilds.push_back(bb);
		reverse(all(bChilds));
		reverse(all(bEdges));
		bEdges.push_back(2 * k);
		while (bw != bb) {
			blossomParent[bw] = b;
			bChilds.push_back(bw);
			bEdges.push_back(labelEdge[bw] ^ 1);
			bw = inBlossom[endPoint[labelEdge[bw]]];
		}
		label[b] = 1;
		labelEdge[b] = labelEdge[bb];
		dualVar[b] = 0;
		BlossomLeaves bl(this, b);
		for (int v; bl.next(v); ) {
			if (label[inBlossom[v]] == 2)
				sVerteices.push_back(v);
			inBlossom[v] = b;
		}
		vi bestEdgeTo(2 * nVertex, -1);
		each(it, bChilds) {
			int bv2 = *it;
			vector<vi> nbLists;
			if (!blossomBestEdgesUsed[bv2]) {
				BlossomLeaves bl2(this, bv2);
				for (int v2; bl2.next(v2); ) {
					nbLists.push_back(neighbEnd[v2]);
					vi &vv = nbLists.back();
					each(i, vv)
						*i /= 2;
				}
			}
			else {
				nbLists.push_back(blossomBestEdges[bv2]);
			}
			each(itt, nbLists) {
				each(ittt, *itt) {
					int k2 = *ittt;
					Edge &e2 = edges[k2];
					int i = e2.src, j = e2.dst;
					if (inBlossom[j] == b)
						swap(i, j);
					int bj = inBlossom[j];
					if (bj != b && label[bj] == 1 &&
						(bestEdgeTo[bj] == -1 ||
							slack(k2) < slack(bestEdgeTo[bj]))) {
						bestEdgeTo[bj] = k2;
					}
				}
			}
			blossomBestEdgesUsed[bv2] = false;
			blossomBestEdges[bv2].clear();
			bestEdge[bv2] = -1;
		}
		blossomBestEdgesUsed[b] = true;
		blossomBestEdges[b].clear();
		each(it, bestEdgeTo)
			if (*it != -1)
				blossomBestEdges[b].push_back(*it);
		bestEdge[b] = -1;
		each(it, blossomBestEdges[b])
			if (bestEdge[b] == -1 || slack(*it) < slack(bestEdge[b]))
				bestEdge[b] = *it;
	}
	void expandBlossom(int b, bool endStage) {
		int cSize = blossomChilds[b].size();
		each(it, blossomChilds[b]) {
			int s = *it;
			blossomParent[s] = -1;
			if (s < nVertex)
				inBlossom[s] = s;
			else if (endStage && dualVar[s] == 0)
				expandBlossom(s, endStage);
			else {
				BlossomLeaves bl(this, s);
				for (int v; bl.next(v); )
					inBlossom[v] = s;
			}
		}
		if (!endStage && label[b] == 2) {
			int entryChild = inBlossom[endPoint[labelEdge[b] ^ 1]];
			int j = find(all(blossomChilds[b]), entryChild) - blossomChilds[b].begin();
			int jStep, evenOdd;
			if (j & 1)
				jStep = 1, evenOdd = 0;
			else
				jStep = -1, evenOdd = 1;
			int p = labelEdge[b];
			while (j != 0) {
				label[endPoint[p ^ 1]] = 0;
				label[endPoint[blossomEdges[b][j - evenOdd] ^ evenOdd ^ 1]] = 0;
				assignLabel(endPoint[p ^ 1], 2, p);
				allowEdge[blossomEdges[b][j - evenOdd] / 2] = true;
				j = (j + jStep + cSize) % cSize;
				p = blossomEdges[b][j - evenOdd] ^ evenOdd;
				allowEdge[p / 2] = true;
				j = (j + jStep + cSize) % cSize;
			}
			int bv = blossomChilds[b][j];
			label[endPoint[p ^ 1]] = label[bv] = 2;
			labelEdge[endPoint[p ^ 1]] = labelEdge[bv] = p;
			bestEdge[bv] = -1;
			j = (j + jStep + cSize) % cSize;
			while (blossomChilds[b][j] != entryChild) {
				bv = blossomChilds[b][j];
				if (label[bv] == 1) {
					j = (j + jStep + cSize) % cSize;
					continue;
				}
				BlossomLeaves bl(this, bv);
				int v;
				while (bl.next(v))
					if (label[v] != 0)
						break;
				if (label[v] != 0) {
					label[v] = 0;
					label[endPoint[mate[blossomBase[bv]]]] = 0;
					assignLabel(v, 2, labelEdge[v]);
				}
				j = (j + jStep + cSize) % cSize;
			}
		}
		label[b] = labelEdge[b] = -1;
		blossomChilds[b].clear();
		blossomEdges[b].clear();
		blossomBestEdgesUsed[b] = false;
		blossomBestEdges[b].clear();
		bestEdge[b] = -1;
		unusedBlossoms.push_back(b);
	}
	void augmentBlossom(int b, int v) {
		int cSize = blossomChilds[b].size();
		int t = v;
		while (blossomParent[t] != b)
			t = blossomParent[t];
		if (t >= nVertex)
			augmentBlossom(t, v);
		int i, j, jStep, evenOdd;
		i = j = find(all(blossomChilds[b]), t) - blossomChilds[b].begin();
		if (i & 1)
			jStep = 1, evenOdd = 0;
		else
			jStep = -1, evenOdd = 1;
		while (j != 0) {
			j = (j + jStep + cSize) % cSize;
			t = blossomChilds[b][j];
			int p = blossomEdges[b][j - evenOdd] ^ evenOdd;
			if (t >= nVertex)
				augmentBlossom(t, endPoint[p]);
			j = (j + jStep + cSize) % cSize;
			t = blossomChilds[b][j];
			if (t >= nVertex)
				augmentBlossom(t, endPoint[p ^ 1]);
			mate[endPoint[p]] = p ^ 1;
			mate[endPoint[p ^ 1]] = p;
		}
		rotate(blossomChilds[b].begin(), blossomChilds[b].begin() + i, blossomChilds[b].end());
		rotate(blossomEdges[b].begin(), blossomEdges[b].begin() + i, blossomEdges[b].end());
		blossomBase[b] = blossomBase[blossomChilds[b][0]];
	}
	void augmentMatching(int k) {
		Edge &e = edges[k];
		int v = e.src, w = e.dst;
		rep(ii, 2) {
			int s = ii == 0 ? v : w, p = ii == 0 ? 2 * k + 1 : 2 * k;
			while (true) {
				int bs = inBlossom[s];
				if (bs >= nVertex)
					augmentBlossom(bs, s);
				mate[s] = p;
				if (labelEdge[bs] == -1)
					break;
				int bt = inBlossom[endPoint[labelEdge[bs]]];
				s = endPoint[labelEdge[bt]];
				int j = endPoint[labelEdge[bt] ^ 1];
				if (bt >= nVertex)
					augmentBlossom(bt, j);
				mate[j] = labelEdge[bt];
				p = labelEdge[bt] ^ 1;
			}
		}
	}
	void mainLoop() {
		rep(t, nVertex) {
			label.assign(2 * nVertex, 0);
			bestEdge.assign(2 * nVertex, -1);
			fill(blossomBestEdgesUsed.begin() + nVertex, blossomBestEdgesUsed.end(), false);
			allowEdge.assign(nEdge, false);
			sVerteices.clear();
			rep(v, nVertex)
				if (mate[v] == -1 && label[inBlossom[v]] == 0)
					assignLabel(v, 1, -1);
			bool augmented = false;
			while (true) {
				Weight kSlack;
				while (!sVerteices.empty() && !augmented) {
					int v = sVerteices.back(); sVerteices.pop_back();
					each(it, neighbEnd[v]) {
						int p = *it;
						int k = p / 2, w = endPoint[p];
						if (inBlossom[v] == inBlossom[w])
							continue;
						if (!allowEdge[k]) {
							kSlack = slack(k);
							if (kSlack <= 0)
								allowEdge[k] = true;
						}
						if (allowEdge[k]) {
							if (label[inBlossom[w]] == 0) {
								assignLabel(w, 2, p ^ 1);
							}
							else if (label[inBlossom[w]] == 1) {
								int base = scanBlossom(v, w);
								if (base >= 0) {
									addBlossom(base, k);
								}
								else {
									augmentMatching(k);
									augmented = true;
									break;
								}
							}
							else if (label[w] == 0) {
								label[w] = 2;
								labelEdge[w] = p ^ 1;
							}
						}
						else if (label[inBlossom[w]] == 1) {
							int b = inBlossom[v];
							if (bestEdge[b] == -1 || kSlack < slack(bestEdge[b]))
								bestEdge[b] = k;
						}
						else if (label[w] == 0) {
							if (bestEdge[w] == -1 || kSlack < slack(bestEdge[w]))
								bestEdge[w] = k;
						}
					}
				}
				if (augmented)
					break;
				int deltaType = -1;
				Weight delta;
				int deltaEdge, deltaBlossom;
				if (!maxCardinality) {
					deltaType = 1;
					delta = *min_element(dualVar.begin(), dualVar.begin() + nVertex);
				}
				rep(v, nVertex) {
					if (label[inBlossom[v]] == 0 && bestEdge[v] != -1) {
						Weight d = slack(bestEdge[v]);
						if (deltaType == -1 || d < delta) {
							delta = d;
							deltaType = 2;
							deltaEdge = bestEdge[v];
						}
					}
				}
				rep(b, 2 * nVertex) {
					if (blossomParent[b] == -1 && label[b] == 1 && bestEdge[b] != -1) {
						kSlack = slack(bestEdge[b]);
						Weight d = kSlack / 2;
						if (deltaType == -1 || d < delta) {
							delta = d;
							deltaType = 3;
							deltaEdge = bestEdge[b];
						}
					}
				}
				reu(b, nVertex, 2 * nVertex) {
					if (blossomBase[b] >= 0 && blossomParent[b] == -1 &&
						label[b] == 2 &&
						(deltaType == -1 || dualVar[b] < delta)) {
						delta = dualVar[b];
						deltaType = 4;
						deltaBlossom = b;
					}
				}
				if (deltaType == -1) {
					deltaType = 1;
					delta = max((Weight)0, *min_element(dualVar.begin(), dualVar.begin() + nVertex));
				}
				rep(v, nVertex) {
					if (label[inBlossom[v]] == 1) {
						dualVar[v] -= delta;
					}
					else if (label[inBlossom[v]] == 2) {
						dualVar[v] += delta;
					}
				}
				reu(b, nVertex, 2 * nVertex) {
					if (blossomBase[b] >= 0 && blossomParent[b] == -1) {
						if (label[b] == 1) {
							dualVar[b] += delta;
						}
						else if (label[b] == 2) {
							dualVar[b] -= delta;
						}
					}
				}
				if (deltaType == 1) {
					break;
				}
				else if (deltaType == 2) {
					allowEdge[deltaEdge] = true;
					Edge &e = edges[deltaEdge];
					int i = e.src, j = e.dst;
					if (label[inBlossom[i]] == 0)
						swap(i, j);
					sVerteices.push_back(i);
				}
				else if (deltaType == 3) {
					allowEdge[deltaEdge] = true;
					Edge &e = edges[deltaEdge];
					int i = e.src;
					sVerteices.push_back(i);
				}
				else if (deltaType == 4) {
					expandBlossom(deltaBlossom, false);
				}
			}
			if (!augmented)
				break;
			reu(b, nVertex, 2 * nVertex)
				if (blossomParent[b] == -1 && blossomBase[b] >= 0 &&
					label[b] == 1 && dualVar[b] == 0)
					expandBlossom(b, true);
		}
	}
	vi matching(const Edges& edges_, bool maxCardinality_ = false) {
		edges = edges_; maxCardinality = maxCardinality_;
		nEdge = edges.size();
		nVertex = 0;
		each(i, edges) {
			if (i->src >= nVertex) nVertex = i->src + 1;
			if (i->dst >= nVertex) nVertex = i->dst + 1;
		}
		maxWeight = 0;
		endPoint.clear();
		neighbEnd.assign(nVertex, vi());
		rep(i, nEdge) {
			Edge &e = edges[i];
			maxWeight = max(maxWeight, e.weight);
			endPoint.push_back(e.src);
			endPoint.push_back(e.dst);
			neighbEnd[e.src].push_back(2 * i + 1);
			neighbEnd[e.dst].push_back(2 * i);
		}
		mate.assign(nVertex, -1);
		label.assign(2 * nVertex, 0);
		labelEdge.assign(2 * nVertex, -1);
		inBlossom.clear();
		blossomBase.clear();
		blossomParent.assign(2 * nVertex, -1);
		blossomChilds.assign(2 * nVertex, vi());
		blossomEdges.assign(2 * nVertex, vi());
		bestEdge.assign(2 * nVertex, -1);
		blossomBestEdgesUsed.assign(2 * nVertex, false);
		blossomBestEdges.assign(2 * nVertex, vi());
		unusedBlossoms.clear();
		dualVar.clear();
		rep(i, nVertex)
			inBlossom.push_back(i),
			blossomBase.push_back(i),
			unusedBlossoms.push_back(nVertex + i),
			dualVar.push_back(maxWeight);
		rep(i, nVertex)
			blossomBase.push_back(-1),
			dualVar.push_back(0);
		allowEdge.assign(nEdge, 0);
		sVerteices = vi();
		mainLoop();
		rep(v, nVertex)
			if (mate[v] >= 0)
				mate[v] = endPoint[mate[v]];
		return mate;
	}
	Weight getWeight(const Edges& e, bool maxCardinality_ = false) {
		vector<int> v = matching(e, maxCardinality_);
		Weight w = 0;
		rep(i, v.size()) if (v[i] != -1)
			each(j, e) if (i == j->src && j->dst == v[i]) w += j->weight;
		return w;
	}
};

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N, A, B; cin >> N >> A >> B;
	vector<int> a(N), b(N); for (int i = 0; i < N; i++) {
		cin >> a[i] >> b[i];
	}

	int ans = 0;
	vector<bool> used(N);
	for (int i = 0; i < N; i++) {
		if (abs(a[i] - b[i]) <= A || (abs(a[i] - b[i]) >= B&&abs(a[i] - b[i]) <= 2 * A)) {
			ans++;
			used[i] = true;
			dump(i);
		}
	}
	Edges edges;
	for (int i = 0; i < N; i++) {
		if (used[i])continue;
		for (int j = i + 1; j < N; j++) {
			if (used[j])continue;
			dump(i, j, abs(a[i] + a[j] - b[i] - b[j]));
			if (abs(a[i] + a[j] - b[i] - b[j]) <= A || (abs(a[i] + a[j] - b[i] - b[j]) >= B&&abs(a[i] + a[j] - b[i] - b[j]) <= 2 * A)) {
				edges.emplace_back(i, j, 1);
			}
		}
	}
	MaxWeightMatching mwm;
	ans += mwm.getWeight(edges);
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4680
final_rank: 6

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;


////フォード - ファルカーソン法 O(Flow|E|)

typedef int Weight;

const Weight INF = 1e9;
const Weight ZERO = 0;
struct Edge {
	int src, dst;
	Weight weight;
	int rev;
	int id;
	Edge(int src_, int dst_, Weight weight_, const int rev_, const int id_) :
		src(src_), dst(dst_), weight(weight_), rev(rev_), id(id_) { }
	Edge(int src_, int dst_, Weight weight_, const int rev_) :
		src(src_), dst(dst_), weight(weight_), rev(rev_) { }
	Edge() :src(0), dst(0), weight(0) {
	}
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
	e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;
void add_edge(Graph&g, int from, int to, int cap)
{
	g[from].push_back(Edge(from, to, cap, (int)g[to].size()));
	g[to].push_back(Edge(to, from, 0, (int)g[from].size() - 1));
}
//二つを繋ぐ線を完全に消す
void erase_edge(Graph&g, const  int from, const int to) {
	g[from].erase(remove_if(g[from].begin(), g[from].end(), [=](const Edge&e) {return e.dst == to; }), g[from].end());
	g[to].erase(remove_if(g[to].begin(), g[to].end(), [=](const Edge&e) {return e.dst == from; }), g[to].end());
}
int dfs(vector<int>&used, Graph&g, int now, int t, int f)
{
	if (now == t) {
		return f;
	}
	used[now] = true;
	for (int i = 0; i<g[now].size(); ++i) {
		Edge &e = g[now][i];
		if (!used[e.dst] && e.weight>0) {
			int d = dfs(used, g, e.dst, t, min(f, e.weight));
			if (d > 0) {
				e.weight -= d;
				g[e.dst][e.rev].weight += d;
				return d;
			}
		}
	}
	return 0;
}
Weight fold_falc(Graph g, const int start, const int goal) {
	Weight ans = 0;
	while (1) {
		vector<int>used(g.size());
		int flow = dfs(used, g, start, goal, INF);
		if (!flow)return ans;
		else ans += flow;
	}
}

int main() {
	int N,A,B;cin>>N>>A>>B;
	vector<vector<int>>sas(2);
	int ans=0;
	for (int i = 0; i < N; ++i) {
		int a, b;cin>>a>>b;
		int num=a-b;
		if ( abs(num)<=A || (B <= abs(num) && abs(num) <= 2 * A)) {
			ans++;
		}
		else {
			if(num>0)sas[0].push_back(num);
			else sas[1].push_back(-num);
		}
	}
	const int start=0;
	const int zero=1;
	const int one=zero+sas[0].size();
	const int goal=one+sas[1].size();
	Graph g(goal+1);

	for (int i = 0; i < sas[0].size(); ++i) {
		add_edge(g,start,zero+i,1);
	}
	for (int i = 0; i < sas[0].size(); ++i) {
		for (int j = 0; j < sas[1].size(); ++j) {
			int x=zero+i;
			int y=one+j;
			int num=sas[0][i]-sas[1][j];

			if ( abs(num)<=A || (B <= (abs(num)) && (abs(num)) <= 2 * A)) {
				add_edge(g,x,y,1);
			}
		}
	}
	for (int i = 0; i < sas[1].size(); ++i) {
		add_edge(g, one+i, goal, 1);
	}

	ans+=fold_falc(g,start,goal);
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6468
final_rank: 8

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-8)

using namespace std;

#define IINF INT_MAX
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef VVI matrix;

#define MAX 810
double A[MAX][MAX],B[MAX][MAX];

int rnk(int n){
  int res = 0;
  //matrix B(n,VI(n+1,1));
  rep(i,n) rep(j,n+1) B[i][j] = 1;
 
  for(int i=0;i<n;i++) for(int j=0;j<n;j++) B[i][j] = A[i][j];
   
  for(int i=0;i<n;i++){
    int pivot = i;
    for(int j=i;j<n;j++){
      if(abs(B[j][i]) > abs(B[pivot][i])) pivot = j;
    }
    swap(B[i],B[pivot]);
    if(abs(B[i][i]) > EPS) res++;
 
     
    if(abs(B[i][i]) > EPS){
      for(int j=i+1;j<=n;j++) B[i][j] /= B[i][i];
      for(int j=0;j<n;j++){
        if(i != j){
          for(int k=i+1;k<=n;k++) B[j][k] -= B[j][i] * B[i][k];
        }
      }
    }
  }
  return res;
}



int main() {
  srand((unsigned int)time(NULL));
  int N,a,b,c,d,e,n,cnt=0;
  cin >> N >> a >> b;
  vector<int> s,t;
  rep(i,N) {
    cin >> c >> d;
    e = abs(c-d);
    if( e <= a || ( b <= e && e <= 2 * a ) ) ++cnt;
    else s.push_back(c), t.push_back(d);
  }
  n = (int)s.size();
  rep(i,n) {
    REP(j,i+1,n) {
      e = abs( ( s[i] + s[j] ) - ( t[i] + t[j] ) );
      if( e <= a || ( b <= e && e <= 2 * a ) ) {
	A[i][j] = rand() % 1000000;
	A[j][i] = -A[i][j];
      }
    }
  }
  cout << cnt + (int)(rnk(n)/2) << endl;
  return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 12616
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
struct Dinic{
  const int INF=1<<28;
  struct edge {
    int to,cap,rev;
    edge(){}
    edge(int to,int cap,int rev):to(to),cap(cap),rev(rev){}
  };

  int n;
  vector<vector<edge> > G;
  vector<map<int,int> > M;
  vector<int> level,iter;

  Dinic(){}
  Dinic(int sz):n(sz),G(n),M(n),level(n),iter(n){}
  
  void add_edge(int from,int to,int cap){
    M[from][to]=G[from].size();
    M[to][from]=G[to].size();
    G[from].push_back(edge(to,cap,G[to].size()));
    G[to].push_back(edge(from,0,G[from].size()-1));
  }
  
  void bfs(int s){
    fill(level.begin(),level.end(),-1);
    queue<int> que;
    level[s]=0;
    que.push(s);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int i=0;i<(int)G[v].size();i++){
        edge &e = G[v][i];
        if(e.cap>0&&level[e.to]<0){
          level[e.to]=level[v]+1;
          que.push(e.to);
        }
      }
    }
  }
  int dfs(int v,int t,int f){
    if(v==t) return f;
    for(int &i=iter[v];i<(int)G[v].size();i++){
      edge &e=G[v][i];
      if(e.cap>0&&level[v]<level[e.to]){
        int d = dfs(e.to,t,min(f,e.cap));
       if(d>0){
         e.cap-=d;
         G[e.to][e.rev].cap+=d;
         return d;
       }
      }
    }
    return 0;
  }
  int flow(int s,int t,int lim){
    int fl=0;
    for(;;){
      bfs(s);
      if(level[t]<0||lim==0) return fl;
      fill(iter.begin(),iter.end(),0);
      int f;
      while((f=dfs(s,t,lim))>0){
       fl+=f;
       lim-=f;
      }
    }
  }
};

int N,A,B,ans,a,b;
vector<P>C1,C2;

bool check(int a,int b){
  int X=abs(a-b);
  return X<=A||(B<=X&&X<=2*A);
}

int main(){

  cin>>N>>A>>B;

  for(int i=0;i<N;i++){
    cin>>a>>b;
    if(check(a,b))ans++;
    else{
      if(a==b)continue;
      if(a>b)C1.push_back(P(a,b));
      else C2.push_back(P(a,b));
    }
  }

  int c1=C1.size(),c2=C2.size();

  Dinic D(c1+c2+2);

  for(int i=0;i<C1.size();i++){
    for(int j=0;j<C2.size();j++){
      int a=C1[i].first+C2[j].first;
      int b=C1[i].second+C2[j].second;
      if(check(a,b)){
        D.add_edge(i,C1.size()+j,1);
      }
    }
  }

  for(int i=0;i<C1.size();i++)D.add_edge(c1+c2,i,1);
  for(int i=0;i<C2.size();i++)D.add_edge(c1+i,c1+c2+1,1);

  cout<<ans+D.flow(c1+c2,c1+c2+1,1e8)<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 7744
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define REP(i, a, n) for(ll i = ((ll) a); i < ((ll) n); i++)
using namespace std;
typedef long long ll;

class MaxFlow {
public:
  struct edge { ll to, cap, rev; };

  const ll INF = 1LL << 60;
  ll N;
  vector< vector<edge> > E;
  vector<bool> used;

  MaxFlow(ll n): N(n), E(n), used(n) {};

  void add_directed_edge(ll from, ll to, ll cap) {
    E[from].push_back((edge) { to, cap, (ll) E[to].size() });
    E[to].push_back((edge) { from, 0, (ll) E[from].size() - 1 });
  }

  void add_undirected_edge(ll from, ll to, ll cap) {
    E[from].push_back((edge) { to, cap, (ll) E[to].size() });
    E[to].push_back((edge) { from, cap, (ll) E[from].size() - 1 });
  }

  ll dfs(ll v, ll t, ll f) {
    if(v == t) return f;
    used[v] = true;
    REP(i, 0, E[v].size()) {
      edge &e = E[v][i];
      if(!used[e.to] && e.cap > 0) {
        ll d = dfs(e.to, t, min(f, e.cap));
        if(d > 0) {
          e.cap -= d;
          E[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }

  ll max_flow(ll s, ll t) {
    ll flow = 0;
    while(1) {
      REP(i, 0, N) used[i] = false;
      ll f = dfs(s, t, INF);
      if(f == 0 || f == INF) break;
      flow += f;
    }
    return flow;
  }
};

int main(void) {
  ll N, A, B;
  cin >> N >> A >> B;
  vector<ll> a(N), b(N);
  REP(i, 0, N) cin >> a[i] >> b[i];

  ll ans = 0;
  vector<bool> used(N, false);
  REP(i, 0, N) {
    ll d = abs(a[i] - b[i]);
    if(d <= A || (B <= d && d <= 2 * A)) {
      used[i] = true;
      ans++;
    }
  }

  const ll s = N, t = N + 1;
  MaxFlow flow(N + 2);
  REP(i, 0, N) if(!used[i]) {
    ll d = a[i] - b[i];
    if(d > 0) flow.add_directed_edge(s, i, 1);
    if(d < 0) flow.add_directed_edge(i, t, 1);
  }
  REP(i, 0, N) REP(j, 0, N) if(!used[i] && !used[j]) {
    ll di = a[i] - b[i];
    ll dj = a[j] - b[j];
    ll d = abs(di + dj);
    if(d <= A || (B <= d && d <= 2 * A)) {
      if(di > 0 && dj < 0) flow.add_directed_edge(i, j, 1);
      if(di < 0 && dj > 0) flow.add_directed_edge(j, i, 1);
    }
  }
  ans += flow.max_flow(s, t);

  cout << ans << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 8060
final_rank: 11

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template<class S,class T> ostream& operator << (ostream& out,const pair<S,T>& o){ out << "(" << o.first << "," << o.second << ")"; return out; }
template<class T> ostream& operator << (ostream& out,const vector<T> V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; }
template<class T> ostream& operator << (ostream& out,const vector<vector<T> > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; }
template<class S,class T> ostream& operator << (ostream& out,const map<S,T> mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; }


/*
<url:https://onlinejudge.u-aizu.ac.jp/services/room.html#RitsCamp18Day2/problems/G>
問題文============================================================

 N個の非負整数のペア(ai,bi)と非負整数A, B が与えられる。
 以下のいずれかの操作をできるだけたくさん行いたい。
 
 (1) |ai−bi|≤A または B≤|ai−bi|≤2Aを満たす要素iを取り出し、削除する
 (2) |(ai+aj)−(bi+bj)|≤A または B≤|(ai+aj)−(bi+bj)|≤2A を満たす要素iと要素j (i≠j)の組を取り出し、削除する
 
 最大の操作回数を求めよ。
 
=================================================================

解説=============================================================

 出来うる限り　操作(1)を行う
 その後、余った要素ペアに関して操作(2)の条件を満たすペアとの二部マッチングを解く
 
================================================================
*/

ll V;
vector<vector<ll>> G;
vector<ll> match;
vector<int> used;

void add_edge(ll u, ll v) {
    G[u].push_back(v);
    G[v].push_back(u);
}

bool dfs(ll v) {
    used[v] = 1;
    for (int i = 0; i < G[v].size(); i++) {
        ll u = G[v][i], w = match[u];
        if (w < 0 || ((used[w] == 0) && dfs(w))) {
            match[v] = u;
            match[u] = v;
            return true;
        }
    }
    return false;
}

ll bipartite_matching() {
    ll res = 0;
    for (int i = 0; i < (int)match.size();i++)match[i] = -1;
    for (int v = 0;v < V;v++) {
        if (match[v] < 0) {
            for (int i = 0; i < (int)used.size();i++)used[i] = 0;
            if (dfs(v))res++;
        }
    }
    return res;
}

int main(void) {
	cin.tie(0); ios::sync_with_stdio(false);
    ll N,A,B; cin >> N >> A >> B;
    vector<ll> a(N),b(N);
    for(int i = 0; i < N;i++) cin >> a[i] >>b[i];
    
    vector<int> f(N,0);
    for(int i = 0; i < N;i++){
        ll Abs = abs(a[i]-b[i]);
        if(Abs <= A || (B <= Abs && Abs <= 2*A)){
            f[i] = -1;
        }
    }
    ll cnt = -accumulate(f.begin(),f.end(),0LL);
    V = 0;
    for(int i = 0; i < N;i++){
        if(f[i] == 0){
            f[i] = V;
            V++;
        }
    }
    G.resize(V);
    match.resize(V);
    used.resize(V);
    
    for(int i = 0; i < N;i++){
        for(int j = 0; j < N;j++){
            if(f[i] == -1 || f[j] == -1) continue;
            ll Absdayo = abs(a[i]+a[j]-b[i]-b[j]);
            if(Absdayo <= A || (B <= Absdayo && Absdayo <= 2*A )){
                 add_edge(f[i],f[j]);
            }
        }
    }
//    cout << cnt << " " << bipartite_matching() << endl;
    cout << cnt + bipartite_matching() << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4648
final_rank: 5

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template<class S,class T> ostream& operator << (ostream& out,const pair<S,T>& o){ out << "(" << o.first << "," << o.second << ")"; return out; }
template<class T> ostream& operator << (ostream& out,const vector<T> V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; }
template<class T> ostream& operator << (ostream& out,const vector<vector<T> > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; }
template<class S,class T> ostream& operator << (ostream& out,const map<S,T> mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; }


/*
<url:>
問題文============================================================

=================================================================

解説=============================================================

================================================================
*/

ll V;
vector<vector<ll>> G;
vector<ll> match;
vector<int> used;

void add_edge(ll u, ll v) {
    G[u].push_back(v);
    G[v].push_back(u);
}

bool dfs(ll v) {
    used[v] = 1;
    for (int i = 0; i < G[v].size(); i++) {
        ll u = G[v][i], w = match[u];
        if (w < 0 || ((used[w] == 0) && dfs(w))) {
            match[v] = u;
            match[u] = v;
            return true;
        }
    }
    return false;
}

ll bipartite_matching() {
    ll res = 0;
    for (int i = 0; i < (int)match.size();i++)match[i] = -1;
    for (int v = 0;v < V;v++) {
        if (match[v] < 0) {
            for (int i = 0; i < (int)used.size();i++)used[i] = 0;
            if (dfs(v))res++;
        }
    }
    return res;
}

int main(void) {
	cin.tie(0); ios::sync_with_stdio(false);
    ll N,A,B; cin >> N >> A >> B;
    vector<ll> a(N),b(N);
    for(int i = 0; i < N;i++) cin >> a[i] >>b[i];
    
    vector<int> f(N,0);
    for(int i = 0; i < N;i++){
        ll Abs = abs(a[i]-b[i]);
        if(Abs <= A || (B <= Abs && Abs <= 2*A)){
            f[i] = -1;
        }
    }
    ll cnt = -accumulate(f.begin(),f.end(),0LL);
    V = 0;
    for(int i = 0; i < N;i++){
        if(f[i] == 0){
            f[i] = V;
            V++;
        }
    }
    G.resize(V);
    match.resize(V);
    used.resize(V);
    
    for(int i = 0; i < N;i++){
        for(int j = 0; j < N;j++){
            if(f[i] == -1 || f[j] == -1) continue;
            ll Absdayo = abs(a[i]+a[j]-b[i]-b[j]);
            if(Absdayo <= A || (B <= Absdayo && Absdayo <= 2*A )){
                 add_edge(f[i],f[j]);
            }
        }
    }
//    cout << cnt << " " << bipartite_matching() << endl;
    cout << cnt + bipartite_matching() << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4480
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define FOR(i,a,b) for(int i=(int)(a);i<(int)(b);i++)

#define CHMIN(a,b) (a)=min((a),(b))
#define CHMAX(a,b) (a)=max((a),(b))

typedef long long ll;

int N,A,B;
int a[830], b[830];
int c[830];

bool g[830][830];

int main(){
  scanf("%d%d%d",&N,&A,&B);
  REP(i,N)scanf("%d%d",a+i,b+i);
  REP(i,N)c[i] = a[i]-b[i];
  int ans = 0;
  vector<int> pos, neg;
  REP(i,N){
    if(abs(c[i])<=A || (B<=abs(c[i]) && abs(c[i])<=2*A)){
      ans++;
    }else{
      (c[i]<0 ? neg : pos).push_back(c[i]);
    }
  }
  int n = pos.size(), m = neg.size();
  REP(i,n)REP(j,m){
    int x = pos[i] + neg[j];
    if(abs(x)<=A || (B<=abs(x) && abs(x)<=2*A)){
      g[i][n+j] = true;
    }else{
      g[i][n+j] = false;
    }
  }
  int s = n+m;
  int t = n+m+1;
  REP(i,n)g[s][i] = true;
  REP(j,m)g[n+j][t] = true;
  while(true){
    vector<int> bef(n+m+2, -1);
    vector<bool> used(n+m+2, false);
    stack<int> S;
    S.push(s);
    used[s] = true;
    while(!S.empty()){
      int p = S.top(); S.pop();
      REP(to,n+m+2)if(!used[to]){
        if(!g[p][to])continue;
        used[to] = true;
        bef[to] = p;
        S.push(to);
      }
    }
    if(!used[t])break;
    int cur = t;
    while(cur != s){
      int b = bef[cur];
      g[b][cur] = false;
      g[cur][b] = true;
      cur = b;
    }
    ans++;
  }
  printf("%d\n",ans);
  return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 3848
final_rank: 19

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define all(a) (a).begin(),(a).end()
#define pb emplace_back
#define INF (1e9+1)


//2部最大マッチング verified AOJ GRL_7_A
#define MAX_V 800
vector<int> G[MAX_V];
int match[MAX_V];
bool used[MAX_V];

void add_edge(int u,int v){
    G[u].pb(v);
    G[v].pb(u);
}

// 増大路をDFSで探す
bool dfs(int v){
    used[v]=true;
    rep(i,G[v].size()){
        int u=G[v][i],w=match[u];           //u:vからの移動先の頂点 , w:uとマッチングしている頂点
        if(w<0 || (!used[w] && dfs(w))){    //uがフリーか、このdfsではwを使っておらず かつwの別のペアが見つかった(=増大路発見) 場合
            match[v]=u;
            match[u]=v;
            return true;
        }
    }
    return false;
}

int bipartite_matching(int V){
    int res=0;
    rep(i,MAX_V)match[i]=-1;
    rep(v,V){
        if(match[v]<0){
            rep(i,MAX_V)used[i]=0;
            if( dfs(v) ) res++;       //増大路が見つかればres+=1
        }
    }
    return res;
}

int main(){
    int ans = 0;
    int v,a,b;
    cin>>v>>a>>b;
    
    vector<int> s(v),t(v);
    rep(i,v){
        cin>>s[i]>>t[i];
        if(abs(s[i]-t[i])<=a or (b<=abs(s[i]-t[i]) and abs(s[i]-t[i])<=2*a))ans++;
    }
    
    auto g = [](int ai,int bi, int aj, int bj){
        return abs((ai+aj)-(bi+bj));
    };
    
    rep(i,v){
        if(abs(s[i]-t[i])<=a or (b<=abs(s[i]-t[i]) and abs(s[i]-t[i])<=2*a))continue;
        rep(j,v){
            if(abs(s[j]-t[j])<=a or (b<=abs(s[j]-t[j]) and abs(s[j]-t[j])<=2*a))continue;
            
            if(g(s[i],t[i],s[j],t[j])<=a or (b<=g(s[i],t[i],s[j],t[j]) and g(s[i],t[i],s[j],t[j])<=2*a) ){
                G[i].pb(j);
            }
        }
    }
    cout<<bipartite_matching(v)+ans<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3464
final_rank: 1

code_snippet: #include <cstdio>
#include <cassert>

#include <vector>

using namespace std;

class MaximumMatching {
  /*
    Maximum Cardinality Matching in General Graphs.
    - O(\sqrt{n} m \log_{\max\{2, 1 + m/n\}} n) time
    - O(n + m) space 
    Note: each vertex is 1-indexed.
    Ref: 
      Harold N. Gabow,
      "The Weighted Matching Approach to Maximum Cardinality Matching" (2017)
      (https://arxiv.org/abs/1703.03998)
  */
public:
  struct Edge { int from, to; };
  static constexpr int Inf = 1 << 30;

private:
  enum Label { 
    kInner = -1, // should be < 0
    kFree = 0    // should be 0
  };
  struct Link { int from, to; };
  struct Log { int v, par; };

  struct LinkedList {
    LinkedList() {}
    LinkedList(int N, int M) : N(N), next(M) { clear(); }
    void clear() { head.assign(N, -1); }
    void push(int h, int u) { next[u] = head[h], head[h] = u; }
    int N;
    vector<int> head, next;
  };

  template <typename T>
  struct Queue {
    Queue() {}
    Queue(int N) : qh(0), qt(0), data(N) {}
    T operator [] (int i) const { return data[i]; }
    void enqueue(int u) { data[qt++] = u; }
    int dequeue() { return data[qh++]; }
    bool empty() const { return qh == qt; }
    void clear() { qh = qt = 0; }
    int size() const { return qt; }
    int qh, qt;
    vector<T> data;
  };

  struct DisjointSetUnion {
    DisjointSetUnion() {}
    DisjointSetUnion(int N) : par(N) {
      for (int i = 0; i < N; ++i) par[i] = i;
    }
    int find(int u) { return par[u] == u ? u : (par[u] = find(par[u])); }
    void unite(int u, int v) {
      u = find(u), v = find(v);
      if (u != v) par[v] = u;
    }
    vector<int> par;
  };

public:
  MaximumMatching(int N, const vector<Edge>& in)
      : N(N), NH(N >> 1), ofs(N + 2, 0), edges(in.size() * 2) {

    for (auto& e : in) ofs[e.from + 1] += 1, ofs[e.to + 1] += 1;
    for (int i = 1; i <= N + 1; ++i) ofs[i] += ofs[i - 1];
    for (auto& e : in) {
      edges[ofs[e.from]++] = e; edges[ofs[e.to]++] = {e.to, e.from};
    }
    for (int i = N + 1; i > 0; --i) ofs[i] = ofs[i - 1];
    ofs[0] = 0;
  }

  int maximum_matching() {
    initialize();
    int match = 0;
    while (match * 2 + 1 < N) {
      reset_count();
      bool has_augmenting_path = do_edmonds_search();
      if (!has_augmenting_path) break;
      match += find_maximal();
      clear();
    }
    return match;
  }

private:
  void reset_count() {
    time_current_ = 0; time_augment_ = Inf;
    contract_count_ = 0; outer_id_ = 1;
    dsu_changelog_size_ = dsu_changelog_last_ = 0;
  }

  void clear() {
    que.clear();
    for (int u = 1; u <= N; ++u) potential[u] = 1;
    for (int u = 1; u <= N; ++u) dsu.par[u] = u;
    for (int t = time_current_; t <= N / 2; ++t) list.head[t] = -1;
    for (int u = 1; u <= N; ++u) blossom.head[u] = -1;
  }

  // first phase

  inline void grow(int x, int y, int z) {
    label[y] = kInner;
    potential[y] = time_current_; // visited time
    link[z] = {x, y}; label[z] = label[x];
    potential[z] = time_current_ + 1;
    que.enqueue(z);
  }

  void contract(int x, int y) {
    int bx = dsu.find(x), by = dsu.find(y);
    const int h = -(++contract_count_) + kInner;
    label[mate[bx]] = label[mate[by]] = h;
    int lca = -1;
    while (1) {
      if (mate[by] != 0) swap(bx, by);
      bx = lca = dsu.find(link[bx].from);
      if (label[mate[bx]] == h) break;
      label[mate[bx]] = h;
    }
    for (auto bv : {dsu.par[x], dsu.par[y]}) {
      for (; bv != lca; bv = dsu.par[link[bv].from]) {
        int mv = mate[bv];
        link[mv] = {x, y}; label[mv] = label[x];
        potential[mv] = 1 + (time_current_ - potential[mv]) + time_current_;
        que.enqueue(mv);
        dsu.par[bv] = dsu.par[mv] = lca;
        dsu_changelog[dsu_changelog_last_++] = {bv, lca};
        dsu_changelog[dsu_changelog_last_++] = {mv, lca};
      }
    }
  }

  bool find_augmenting_path() {
    while (!que.empty()) {
      int x = que.dequeue(), lx = label[x], px = potential[x], bx = dsu.find(x);
      for (int eid = ofs[x]; eid < ofs[x + 1]; ++eid) {
        int y = edges[eid].to;
        if (label[y] > 0) { // outer blossom/vertex
          int time_next = (px + potential[y]) >> 1;
          if (lx != label[y]) {
            if (time_next == time_current_) return true;
            time_augment_ = min(time_next, time_augment_);
          } else {
            if (bx == dsu.find(y)) continue;
            if (time_next == time_current_) {
              contract(x, y); bx = dsu.find(x);
            } else if (time_next <= NH) list.push(time_next, eid);
          }
        } else if (label[y] == kFree) { // free vertex
          int time_next = px + 1;
          if (time_next == time_current_) grow(x, y, mate[y]);
          else if (time_next <= NH) list.push(time_next, eid);
        }
      }
    }
    return false;
  }

  bool adjust_dual_variables() {
    // Return true if the current matching is maximum.
    const int time_lim = min(NH + 1, time_augment_);
    for (++time_current_; time_current_ <= time_lim; ++time_current_) {
      dsu_changelog_size_ = dsu_changelog_last_;
      if (time_current_ == time_lim) break;
      bool updated = false;
      for (int h = list.head[time_current_]; h >= 0; h = list.next[h]) {
        auto& e = edges[h]; int x = e.from, y = e.to;
        if (label[y] > 0) {
          // Case: outer -- (free => inner => outer)
          if (potential[x] + potential[y] != (time_current_ << 1)) continue;
          if (dsu.find(x) == dsu.find(y)) continue;
          if (label[x] != label[y]) { time_augment_ = time_current_; return false; }
          contract(x, y); updated = true;
        } else if (label[y] == kFree) {
          grow(x, y, mate[y]); updated = true;
        }
      }
      list.head[time_current_] = -1;
      if (updated) return false;
    }
    return time_current_ > NH;
  }

  bool do_edmonds_search() {
    label[0] = kFree;
    for (int u = 1; u <= N; ++u) {
      if (mate[u] == 0) {
        que.enqueue(u); label[u] = u; // component id
      } else label[u] = kFree;
    }
    while (1) {
      if (find_augmenting_path()) break;
      bool maximum = adjust_dual_variables();
      if (maximum) return false;
      if (time_current_ == time_augment_) break;
    }
    for (int u = 1; u <= N; ++u) {
      if (label[u] > 0) potential[u] -= time_current_;
      else if (label[u] < 0) potential[u] = 1 + (time_current_ - potential[u]);
    }
    return true;
  }

  // second phase

  void rematch(int v, int w) {
    int t = mate[v]; mate[v] = w;
    if (mate[t] != v) return;
    if (link[v].to == dsu.find(link[v].to)) {
      mate[t] = link[v].from;
      rematch(mate[t], t);
    } else {
      int x = link[v].from, y = link[v].to;
      rematch(x, y); rematch(y, x);
    }
  }

  bool dfs_augment(int x, int bx) {
    int px = potential[x], lx = label[bx];
    for (int eid = ofs[x]; eid < ofs[x + 1]; ++eid) {
      int y = edges[eid].to;
      if (px + potential[y] != 0) continue;
      int by = dsu.find(y), ly = label[by];
      if (ly > 0) { // outer
        if (lx >= ly) continue;
        int stack_beg = stack_last_;
        for (int bv = by; bv != bx; bv = dsu.find(link[bv].from)) {
          int bw = dsu.find(mate[bv]);
          stack[stack_last_++] = bw; link[bw] = {x, y};
          dsu.par[bv] = dsu.par[bw] = bx;
        }
        while (stack_last_ > stack_beg) {
          int bv = stack[--stack_last_];
          for (int v = blossom.head[bv]; v >= 0; v = blossom.next[v]) {
            if (!dfs_augment(v, bx)) continue;
            stack_last_ = stack_beg;
            return true;
          }
        }
      } else if (ly == kFree) {
        label[by] = kInner; int z = mate[by];
        if (z == 0) { rematch(x, y); rematch(y, x); return true; }
        int bz = dsu.find(z);
        link[bz] = {x, y}; label[bz] = outer_id_++;
        for (int v = blossom.head[bz]; v >= 0; v = blossom.next[v]) {
          if (dfs_augment(v, bz)) return true;
        }
      }
    }
    return false;
  }

  int find_maximal() {
    // discard blossoms whose potential is 0.
    for (int u = 1; u <= N; ++u) dsu.par[u] = u;
    for (int i = 0; i < dsu_changelog_size_; ++i) {
      dsu.par[dsu_changelog[i].v] = dsu_changelog[i].par;
    }
    for (int u = 1; u <= N; ++u) {
      label[u] = kFree; blossom.push(dsu.find(u), u);
    }
    int ret = 0;
    for (int u = 1; u <= N; ++u) if (!mate[u]) {
      int bu = dsu.par[u];
      if (label[bu] != kFree) continue;
      label[bu] = outer_id_++;
      for (int v = blossom.head[bu]; v >= 0; v = blossom.next[v]) {
        if (!dfs_augment(v, bu)) continue;
        ret += 1;
        break;
      }
    }
    assert(ret >= 1);
    return ret;
  }

  // init

  void initialize() {
    que = Queue<int>(N);

    mate.assign(N + 1, 0);
    potential.assign(N + 1, 1);
    label.assign(N + 1, kFree);
    link.assign(N + 1, {0, 0});

    dsu_changelog.resize(N);

    dsu = DisjointSetUnion(N + 1);
    list = LinkedList(NH + 1, edges.size());

    blossom = LinkedList(N + 1, N + 1);
    stack.resize(N); stack_last_ = 0;
  }

private:
  const int N, NH;
  vector<int> ofs; vector<Edge> edges;

  Queue<int> que;

  vector<int> mate, potential;
  vector<int> label; vector<Link> link;

  vector<Log> dsu_changelog; int dsu_changelog_last_, dsu_changelog_size_;

  DisjointSetUnion dsu;
  LinkedList list, blossom;
  vector<int> stack; int stack_last_;
  
  int time_current_, time_augment_;
  int contract_count_, outer_id_;
};

using Edge = MaximumMatching::Edge;

// main function
#include <iostream>
#include <set>
#include <random>
vector<pair<int,int> >ve;
int a[1000],b[1000];
int main() {

	int n,aa,bb;
	cin>>n>>aa>>bb;
	for(int i=1;i<=n;i++)cin>>a[i]>>b[i];

	
	for(int i=1;i<=n;i++)if(abs(a[i]-b[i])<=aa || (bb<=abs(a[i]-b[i]) && abs(a[i]-b[i])<=2*aa)){
		
		ve.push_back(make_pair(i,i+n));
	}
	for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){
		int f=abs(a[i]+a[j]-b[i]-b[j]);
		if(f<=aa || (bb<=f && f<=2*aa)) {
			ve.push_back(make_pair(i,j));
		}
	}
	
	
	
	
	mt19937 mt(12345);

  auto run = [] (int N, const vector<Edge>& edges) {
    clock_t beg = clock();
    auto mm = MaximumMatching(N, edges);
    auto ans = mm.maximum_matching();
    clock_t end = clock();
   cout<<ans<<endl;
  };

  const int K = 2000;

  // random
  {
  	const int N = K, M = ve.size();
  //  uniform_int_distribution<int> urand(1, N);
    vector<Edge> edges(M);
    for (int i = 0; i < M; ++i) {
    	int u =ve[i].first, v = ve[i].second;
      edges[i] = {u, v};
    }
    run(N, edges);
  }

 
}
accuracy: 1
time_ms: 10
memory_kb: 15148
final_rank: 17

code_snippet: // g++ -std=c++11 a.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>	
#include<map>
#include<set>
#include<utility>
#include<cmath>
#include<random>
#include<cstring>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<sstream>
#include<iomanip>
#include<assert.h>
#include<typeinfo>
#define loop(i,a,b) for(int i=a;i<b;i++) 
#define rep(i,a) loop(i,0,a)
#define pb push_back
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
using namespace std;
//kaewasuretyuui
typedef long long ll;
//#define int ll
typedef int Def;
typedef pair<Def,Def> pii;
typedef vector<Def> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<Def,pii> pip;
typedef vector<pip>vip;
// #define mt make_tuple
//typedef tuple<pii,int,int> tp;
//typedef vector<tp> vt;
template<typename A,typename B>bool cmin(A &a,const B &b){return a>b?(a=b,true):false;}
template<typename A,typename B>bool cmax(A &a,const B &b){return a<b?(a=b,true):false;}
//template<class C>constexpr int size(const C &c){return (int)c.size();}
//template<class T,size_t N> constexpr int size(const T (&xs)[N])noexcept{return (int)N;}
const double PI=acos(-1);
const double EPS=1e-7;
Def inf = sizeof(Def) == sizeof(long long) ? 2e18 : 1e9+10;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
struct edge{int to,cap,rev;};//ikisaki youryou gyakuhen
class MF{//max flow
	public:
	int n;
	vector<vector<edge> >G;//[MAX];
	vector<bool>used;//[MAX];
	MF(int size){
		n=size;
		G=vector<vector<edge> >(n);
	}
	void add_edge(int from, int to, int cap){
		edge q={to,cap,int(G[to].size())};
		G[from].push_back(q);
		q={from,0,int(G[from].size()-1)};
		G[to].push_back(q);
	}
	int dfs(int v,int t, int f) {
		if(v==t)return f;
		used[v]=1;
		for(int i=0;i<G[v].size();i++){
			edge &e=G[v][i];
			if(used[e.to]||e.cap<=0) continue;
			int d =dfs(e.to,t,min(f,e.cap));
			if(d>0){
				e.cap-=d;
				G[e.to][e.rev].cap+=d;
				return d;
			}
		}
		return 0;
	}
	int mf(int s,int t) {//from s to t,ford_fulkerson
		int flow=0,f;
		while(1){
			used=vector<bool>(n,false);
			f=dfs(s,t,inf);
			if(f==0)return flow;
			flow+=f;
		}
	}
};
int main(){
	int n,m,a,b;
	cin>>n>>a>>b;
	vi A,B,in(n);
	rep(i,n){
		int q,w;
		cin>>q>>w;
		in[i]=q-w;
	}
	int out=0;
	rep(i,n)if(abs(in[i])<=a||b<=abs(in[i])&&abs(in[i])<=2*a)out++;
	else if(in[i]>0)A.pb(in[i]);
	else B.pb(in[i]);
	
	n=A.size(),m=B.size();
	MF mf(2+n+m);
	int s=n+m,t=s+1;
	rep(i,n)mf.add_edge(s,i,1);
	rep(i,m)mf.add_edge(n+i,t,1);
	rep(i,n)rep(j,m){
		int w=abs(A[i]+B[j]);
		if(w<=a||b<=w&&w<=2*a)mf.add_edge(i,n+j,1);
	}
	out+=mf.mf(s,t);
	cout<<out<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 4380
final_rank: 3

code_snippet: #include "bits/stdc++.h"
using namespace std;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
static const int INF = 0x3f3f3f3f; static const long long INFL = 0x3f3f3f3f3f3f3f3fLL;
typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pair<int, int> > vpii; typedef long long ll;
template<typename T, typename U> static void amin(T &x, U y) { if (y < x) x = y; }
template<typename T, typename U> static void amax(T &x, U y) { if (x < y) x = y; }
#define each(it,o) for(auto it = (o).begin(); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#ifdef _DEBUG
#include "dump.hpp"
#else
#define dump(...)
#endif

typedef int Weight;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src_, int dst_, Weight weight_) : src(src_), dst(dst_), weight(weight_) { }
	Edge() {};
};
typedef vector<Edge> Edges;
struct MaxWeightMatching {
	int nEdge, nVertex;
	Weight maxWeight;
	vi endPoint, mate, label, labelEdge,
		inBlossom, blossomParent, blossomBase,
		bestEdge, unusedBlossoms, allowEdge,
		blossomBestEdgesUsed,
		sVerteices;
	vector<Weight> dualVar;
	vector<vi> neighbEnd, blossomChilds, blossomEdges,
		blossomBestEdges;
	Edges edges;
	bool maxCardinality;

	Weight slack(int k) {
		Edge &e = edges[k];
		return dualVar[e.src] + dualVar[e.dst] - 2 * e.weight;
	}
	struct BlossomLeaves {
		int b;
		MaxWeightMatching *mw;
		enum { INITAL, END, NEXT, THIRD } state;
		vi::const_iterator iter, endi;
		BlossomLeaves *bl;
		BlossomLeaves(MaxWeightMatching *mw_, int b_) :
			mw(mw_), b(b_), state(INITAL), bl(NULL) {}
		bool next(int &r) {
			int t;
			switch (state) {
			case INITAL:
				if (b < mw->nVertex) {
					r = b;
					state = END;
					return true;
				}
				else {
					iter = mw->blossomChilds[b].begin();
					endi = mw->blossomChilds[b].end();
					state = NEXT;
					return next(r);
				}
			case END:
				return false;
			case NEXT:
				if (iter == endi)
					return false;
				t = *iter;
				++iter;
				if (t < mw->nVertex) {
					r = t;
					return true;
				}
				else {
					bl = new BlossomLeaves(mw, t);
					state = THIRD;
					return next(r);
				}
			case THIRD:
				if (!bl->next(t)) {
					state = NEXT;
					delete bl; bl = NULL;
					return next(r);
				}
				else {
					r = t;
					return true;
				}
			}
			return false;
		}
	};
	void assignLabel(int w, int t, int p) {
		int b = inBlossom[w];
		label[w] = label[b] = t;
		labelEdge[w] = labelEdge[b] = p;
		bestEdge[w] = bestEdge[b] = -1;
		if (t == 1) {
			BlossomLeaves bl(this, b);
			for (int r; bl.next(r); ) sVerteices.push_back(r);
		}
		else if (t == 2) {
			int base = blossomBase[b];
			assignLabel(endPoint[mate[base]], 1, mate[base] ^ 1);
		}
	}
	int scanBlossom(int v, int w) {
		vi path;
		int base = -1;
		while (v != -1) {
			int b = inBlossom[v];
			if (label[b] & 4) {
				base = blossomBase[b];
				break;
			}
			path.push_back(b);
			label[b] = 5;
			if (labelEdge[b] == -1) {
				v = -1;
			}
			else {
				v = endPoint[labelEdge[b]];
				b = inBlossom[v];
				v = endPoint[labelEdge[b]];
			}
			if (w != -1)
				swap(v, w);
		}
		each(it, path)
			label[*it] = 1;
		return base;
	}
	void addBlossom(int base, int k) {
		Edge &e = edges[k];
		int bb = inBlossom[base],
			bv = inBlossom[e.src],
			bw = inBlossom[e.dst];
		int b = unusedBlossoms.back(); unusedBlossoms.pop_back();
		blossomBase[b] = base;
		blossomParent[b] = -1;
		blossomParent[bb] = b;
		blossomChilds[b].clear();
		blossomEdges[b].clear();
		vi &bChilds = blossomChilds[b];
		vi &bEdges = blossomEdges[b];
		while (bv != bb) {
			blossomParent[bv] = b;
			bChilds.push_back(bv);
			bEdges.push_back(labelEdge[bv]);
			bv = inBlossom[endPoint[labelEdge[bv]]];
		}
		bChilds.push_back(bb);
		reverse(all(bChilds));
		reverse(all(bEdges));
		bEdges.push_back(2 * k);
		while (bw != bb) {
			blossomParent[bw] = b;
			bChilds.push_back(bw);
			bEdges.push_back(labelEdge[bw] ^ 1);
			bw = inBlossom[endPoint[labelEdge[bw]]];
		}
		label[b] = 1;
		labelEdge[b] = labelEdge[bb];
		dualVar[b] = 0;
		BlossomLeaves bl(this, b);
		for (int v; bl.next(v); ) {
			if (label[inBlossom[v]] == 2)
				sVerteices.push_back(v);
			inBlossom[v] = b;
		}
		vi bestEdgeTo(2 * nVertex, -1);
		each(it, bChilds) {
			int bv2 = *it;
			vector<vi> nbLists;
			if (!blossomBestEdgesUsed[bv2]) {
				BlossomLeaves bl2(this, bv2);
				for (int v2; bl2.next(v2); ) {
					nbLists.push_back(neighbEnd[v2]);
					vi &vv = nbLists.back();
					each(i, vv)
						*i /= 2;
				}
			}
			else {
				nbLists.push_back(blossomBestEdges[bv2]);
			}
			each(itt, nbLists) {
				each(ittt, *itt) {
					int k2 = *ittt;
					Edge &e2 = edges[k2];
					int i = e2.src, j = e2.dst;
					if (inBlossom[j] == b)
						swap(i, j);
					int bj = inBlossom[j];
					if (bj != b && label[bj] == 1 &&
						(bestEdgeTo[bj] == -1 ||
							slack(k2) < slack(bestEdgeTo[bj]))) {
						bestEdgeTo[bj] = k2;
					}
				}
			}
			blossomBestEdgesUsed[bv2] = false;
			blossomBestEdges[bv2].clear();
			bestEdge[bv2] = -1;
		}
		blossomBestEdgesUsed[b] = true;
		blossomBestEdges[b].clear();
		each(it, bestEdgeTo)
			if (*it != -1)
				blossomBestEdges[b].push_back(*it);
		bestEdge[b] = -1;
		each(it, blossomBestEdges[b])
			if (bestEdge[b] == -1 || slack(*it) < slack(bestEdge[b]))
				bestEdge[b] = *it;
	}
	void expandBlossom(int b, bool endStage) {
		int cSize = blossomChilds[b].size();
		each(it, blossomChilds[b]) {
			int s = *it;
			blossomParent[s] = -1;
			if (s < nVertex)
				inBlossom[s] = s;
			else if (endStage && dualVar[s] == 0)
				expandBlossom(s, endStage);
			else {
				BlossomLeaves bl(this, s);
				for (int v; bl.next(v); )
					inBlossom[v] = s;
			}
		}
		if (!endStage && label[b] == 2) {
			int entryChild = inBlossom[endPoint[labelEdge[b] ^ 1]];
			int j = find(all(blossomChilds[b]), entryChild) - blossomChilds[b].begin();
			int jStep, evenOdd;
			if (j & 1)
				jStep = 1, evenOdd = 0;
			else
				jStep = -1, evenOdd = 1;
			int p = labelEdge[b];
			while (j != 0) {
				label[endPoint[p ^ 1]] = 0;
				label[endPoint[blossomEdges[b][j - evenOdd] ^ evenOdd ^ 1]] = 0;
				assignLabel(endPoint[p ^ 1], 2, p);
				allowEdge[blossomEdges[b][j - evenOdd] / 2] = true;
				j = (j + jStep + cSize) % cSize;
				p = blossomEdges[b][j - evenOdd] ^ evenOdd;
				allowEdge[p / 2] = true;
				j = (j + jStep + cSize) % cSize;
			}
			int bv = blossomChilds[b][j];
			label[endPoint[p ^ 1]] = label[bv] = 2;
			labelEdge[endPoint[p ^ 1]] = labelEdge[bv] = p;
			bestEdge[bv] = -1;
			j = (j + jStep + cSize) % cSize;
			while (blossomChilds[b][j] != entryChild) {
				bv = blossomChilds[b][j];
				if (label[bv] == 1) {
					j = (j + jStep + cSize) % cSize;
					continue;
				}
				BlossomLeaves bl(this, bv);
				int v;
				while (bl.next(v))
					if (label[v] != 0)
						break;
				if (label[v] != 0) {
					label[v] = 0;
					label[endPoint[mate[blossomBase[bv]]]] = 0;
					assignLabel(v, 2, labelEdge[v]);
				}
				j = (j + jStep + cSize) % cSize;
			}
		}
		label[b] = labelEdge[b] = -1;
		blossomChilds[b].clear();
		blossomEdges[b].clear();
		blossomBestEdgesUsed[b] = false;
		blossomBestEdges[b].clear();
		bestEdge[b] = -1;
		unusedBlossoms.push_back(b);
	}
	void augmentBlossom(int b, int v) {
		int cSize = blossomChilds[b].size();
		int t = v;
		while (blossomParent[t] != b)
			t = blossomParent[t];
		if (t >= nVertex)
			augmentBlossom(t, v);
		int i, j, jStep, evenOdd;
		i = j = find(all(blossomChilds[b]), t) - blossomChilds[b].begin();
		if (i & 1)
			jStep = 1, evenOdd = 0;
		else
			jStep = -1, evenOdd = 1;
		while (j != 0) {
			j = (j + jStep + cSize) % cSize;
			t = blossomChilds[b][j];
			int p = blossomEdges[b][j - evenOdd] ^ evenOdd;
			if (t >= nVertex)
				augmentBlossom(t, endPoint[p]);
			j = (j + jStep + cSize) % cSize;
			t = blossomChilds[b][j];
			if (t >= nVertex)
				augmentBlossom(t, endPoint[p ^ 1]);
			mate[endPoint[p]] = p ^ 1;
			mate[endPoint[p ^ 1]] = p;
		}
		rotate(blossomChilds[b].begin(), blossomChilds[b].begin() + i, blossomChilds[b].end());
		rotate(blossomEdges[b].begin(), blossomEdges[b].begin() + i, blossomEdges[b].end());
		blossomBase[b] = blossomBase[blossomChilds[b][0]];
	}
	void augmentMatching(int k) {
		Edge &e = edges[k];
		int v = e.src, w = e.dst;
		rep(ii, 2) {
			int s = ii == 0 ? v : w, p = ii == 0 ? 2 * k + 1 : 2 * k;
			while (true) {
				int bs = inBlossom[s];
				if (bs >= nVertex)
					augmentBlossom(bs, s);
				mate[s] = p;
				if (labelEdge[bs] == -1)
					break;
				int bt = inBlossom[endPoint[labelEdge[bs]]];
				s = endPoint[labelEdge[bt]];
				int j = endPoint[labelEdge[bt] ^ 1];
				if (bt >= nVertex)
					augmentBlossom(bt, j);
				mate[j] = labelEdge[bt];
				p = labelEdge[bt] ^ 1;
			}
		}
	}
	void mainLoop() {
		rep(t, nVertex) {
			label.assign(2 * nVertex, 0);
			bestEdge.assign(2 * nVertex, -1);
			fill(blossomBestEdgesUsed.begin() + nVertex, blossomBestEdgesUsed.end(), false);
			allowEdge.assign(nEdge, false);
			sVerteices.clear();
			rep(v, nVertex)
				if (mate[v] == -1 && label[inBlossom[v]] == 0)
					assignLabel(v, 1, -1);
			bool augmented = false;
			while (true) {
				Weight kSlack;
				while (!sVerteices.empty() && !augmented) {
					int v = sVerteices.back(); sVerteices.pop_back();
					each(it, neighbEnd[v]) {
						int p = *it;
						int k = p / 2, w = endPoint[p];
						if (inBlossom[v] == inBlossom[w])
							continue;
						if (!allowEdge[k]) {
							kSlack = slack(k);
							if (kSlack <= 0)
								allowEdge[k] = true;
						}
						if (allowEdge[k]) {
							if (label[inBlossom[w]] == 0) {
								assignLabel(w, 2, p ^ 1);
							}
							else if (label[inBlossom[w]] == 1) {
								int base = scanBlossom(v, w);
								if (base >= 0) {
									addBlossom(base, k);
								}
								else {
									augmentMatching(k);
									augmented = true;
									break;
								}
							}
							else if (label[w] == 0) {
								label[w] = 2;
								labelEdge[w] = p ^ 1;
							}
						}
						else if (label[inBlossom[w]] == 1) {
							int b = inBlossom[v];
							if (bestEdge[b] == -1 || kSlack < slack(bestEdge[b]))
								bestEdge[b] = k;
						}
						else if (label[w] == 0) {
							if (bestEdge[w] == -1 || kSlack < slack(bestEdge[w]))
								bestEdge[w] = k;
						}
					}
				}
				if (augmented)
					break;
				int deltaType = -1;
				Weight delta;
				int deltaEdge, deltaBlossom;
				if (!maxCardinality) {
					deltaType = 1;
					delta = *min_element(dualVar.begin(), dualVar.begin() + nVertex);
				}
				rep(v, nVertex) {
					if (label[inBlossom[v]] == 0 && bestEdge[v] != -1) {
						Weight d = slack(bestEdge[v]);
						if (deltaType == -1 || d < delta) {
							delta = d;
							deltaType = 2;
							deltaEdge = bestEdge[v];
						}
					}
				}
				rep(b, 2 * nVertex) {
					if (blossomParent[b] == -1 && label[b] == 1 && bestEdge[b] != -1) {
						kSlack = slack(bestEdge[b]);
						Weight d = kSlack / 2;
						if (deltaType == -1 || d < delta) {
							delta = d;
							deltaType = 3;
							deltaEdge = bestEdge[b];
						}
					}
				}
				reu(b, nVertex, 2 * nVertex) {
					if (blossomBase[b] >= 0 && blossomParent[b] == -1 &&
						label[b] == 2 &&
						(deltaType == -1 || dualVar[b] < delta)) {
						delta = dualVar[b];
						deltaType = 4;
						deltaBlossom = b;
					}
				}
				if (deltaType == -1) {
					deltaType = 1;
					delta = max((Weight)0, *min_element(dualVar.begin(), dualVar.begin() + nVertex));
				}
				rep(v, nVertex) {
					if (label[inBlossom[v]] == 1) {
						dualVar[v] -= delta;
					}
					else if (label[inBlossom[v]] == 2) {
						dualVar[v] += delta;
					}
				}
				reu(b, nVertex, 2 * nVertex) {
					if (blossomBase[b] >= 0 && blossomParent[b] == -1) {
						if (label[b] == 1) {
							dualVar[b] += delta;
						}
						else if (label[b] == 2) {
							dualVar[b] -= delta;
						}
					}
				}
				if (deltaType == 1) {
					break;
				}
				else if (deltaType == 2) {
					allowEdge[deltaEdge] = true;
					Edge &e = edges[deltaEdge];
					int i = e.src, j = e.dst;
					if (label[inBlossom[i]] == 0)
						swap(i, j);
					sVerteices.push_back(i);
				}
				else if (deltaType == 3) {
					allowEdge[deltaEdge] = true;
					Edge &e = edges[deltaEdge];
					int i = e.src;
					sVerteices.push_back(i);
				}
				else if (deltaType == 4) {
					expandBlossom(deltaBlossom, false);
				}
			}
			if (!augmented)
				break;
			reu(b, nVertex, 2 * nVertex)
				if (blossomParent[b] == -1 && blossomBase[b] >= 0 &&
					label[b] == 1 && dualVar[b] == 0)
					expandBlossom(b, true);
		}
	}
	vi matching(const Edges& edges_, bool maxCardinality_ = false) {
		edges = edges_; maxCardinality = maxCardinality_;
		nEdge = edges.size();
		nVertex = 0;
		each(i, edges) {
			if (i->src >= nVertex) nVertex = i->src + 1;
			if (i->dst >= nVertex) nVertex = i->dst + 1;
		}
		maxWeight = 0;
		endPoint.clear();
		neighbEnd.assign(nVertex, vi());
		rep(i, nEdge) {
			Edge &e = edges[i];
			maxWeight = max(maxWeight, e.weight);
			endPoint.push_back(e.src);
			endPoint.push_back(e.dst);
			neighbEnd[e.src].push_back(2 * i + 1);
			neighbEnd[e.dst].push_back(2 * i);
		}
		mate.assign(nVertex, -1);
		label.assign(2 * nVertex, 0);
		labelEdge.assign(2 * nVertex, -1);
		inBlossom.clear();
		blossomBase.clear();
		blossomParent.assign(2 * nVertex, -1);
		blossomChilds.assign(2 * nVertex, vi());
		blossomEdges.assign(2 * nVertex, vi());
		bestEdge.assign(2 * nVertex, -1);
		blossomBestEdgesUsed.assign(2 * nVertex, false);
		blossomBestEdges.assign(2 * nVertex, vi());
		unusedBlossoms.clear();
		dualVar.clear();
		rep(i, nVertex)
			inBlossom.push_back(i),
			blossomBase.push_back(i),
			unusedBlossoms.push_back(nVertex + i),
			dualVar.push_back(maxWeight);
		rep(i, nVertex)
			blossomBase.push_back(-1),
			dualVar.push_back(0);
		allowEdge.assign(nEdge, 0);
		sVerteices = vi();
		mainLoop();
		rep(v, nVertex)
			if (mate[v] >= 0)
				mate[v] = endPoint[mate[v]];
		return mate;
	}
	Weight getWeight(const Edges& e, bool maxCardinality_ = false) {
		vector<int> v = matching(e, maxCardinality_);
		Weight w = 0;
		rep(i, v.size()) if (v[i] != -1)
			each(j, e) if (i == j->src && j->dst == v[i]) w += j->weight;
		return w;
	}
};

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N, A, B; cin >> N >> A >> B;
	vector<int> a(N), b(N); for (int i = 0; i < N; i++) {
		cin >> a[i] >> b[i];
	}

	int ans = 0;
	vector<bool> used(N);
	for (int i = 0; i < N; i++) {
		if (abs(a[i] - b[i]) <= A || (abs(a[i] - b[i]) >= B&&abs(a[i] - b[i]) <= 2 * A)) {
			ans++;
			used[i] = true;
			dump(i);
		}
	}
	Edges edges;
	for (int i = 0; i < N; i++) {
		if (used[i])continue;
		for (int j = i + 1; j < N; j++) {
			if (used[j])continue;
			dump(i, j, abs(a[i] + a[j] - b[i] - b[j]));
			if (abs(a[i] + a[j] - b[i] - b[j]) <= A || (abs(a[i] + a[j] - b[i] - b[j]) >= B&&abs(a[i] + a[j] - b[i] - b[j]) <= 2 * A)) {
				edges.emplace_back(i, j, 1);
			}
		}
	}
	MaxWeightMatching mwm;
	ans += mwm.getWeight(edges);
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4784
final_rank: 7