Problem p02774 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define for0(i, N) for (int i = 0; i < (N); ++i)
#define for1n(i, N) for (int i = 1; i <= (N); ++i)
#define for1(i, N) for (int i = 1; i < (N); ++i)
#define forn(i, N) for (int i = 0; i <= (N); ++i)
#define forx(i, N, x) for (int i = (x); i < (N); ++i)
#define forl(i, N, x, a)                                                       \
  for (int i = (x), a = 0; a < (N); i = (i + 1) % (N), ++a)

template <size_t i> std::bitset<i> operator++(std::bitset<i> b, int) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  return b = (unsigned long long)b + 1;
}

template <size_t i> std::bitset<i> operator++(std::bitset<i> b) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  auto temp = b;
  b++;
  return temp;
}

template <size_t i> std::bitset<i> operator--(std::bitset<i> b, int) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  return b = (unsigned long long)b - 1;
}

template <size_t i> std::bitset<i> operator--(std::bitset<i> b) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  auto temp = b;
  b--;
  return temp;
}

using namespace std;

typedef long long ll;
typedef long double ld;
typedef priority_queue<ll> pq;
typedef priority_queue<ll, vector<ll>, greater<ll>> pql;
typedef stack<ll> stk;
typedef queue<ll> qu;
typedef pair<ll, ll> pll;
typedef map<ll, ll> mll;
typedef unordered_map<ll, ll> umll;
typedef set<ll> sll;
typedef unordered_set<ll> usll;
typedef vector<ll> vll;
typedef vector<ld> vld;

// right is true, left is false.
template <class T, class F> T bSearch(T l, T r, F func, T diff = 1) {
  while (std::abs(r - l) > diff) {
    T m = (l + r) / 2;
    (func(m) ? r : l) = m;
  }
  return r;
}

template <class Iterator1, class IteratorDynamic, class Condition, class Func2>
void shakutori(Iterator1 bg1, Iterator1 ed1, IteratorDynamic bg2,
               IteratorDynamic ed2, Condition cond, Func2 func2) {
  auto it2 = bg2;
  for (auto it1 = bg1; it1 != ed1; ++it1) {
    while (it2 != ed2 && cond(it1, it2))
      ++it2;
    func2(it1, it2);
  }
}

int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  ll n, k;
  cin >> n >> k;

  vll minus, plus;
  ll zero = 0;

  for0(i, n) {
    ll a;
    cin >> a;
    if (a > 0) {
      plus.push_back(a);
    } else if (a < 0) {
      minus.push_back(-a);
    } else {
      ++zero;
      assert(a == 0);
    }
  }

  assert(plus.size() + minus.size() + zero == n);
  ll ms = minus.size();
  ll ps = plus.size();

  assert(n * (n - 1) / 2 == ms * ps + ps * zero + zero * ms +
                                zero * (zero - 1) / 2 + ps * (ps - 1) / 2 +
                                ms * (ms - 1) / 2);

  // cerr << "all: "
  //     << ms * ps + ps * zero + zero * ms +
  //     zero * (zero - 1) / 2 + ps *(ps - 1) / 2 + ms *(ms - 1) / 2 << "\n";

  ll m = ms * ps;
  ll z = zero * ps + zero * ms + zero * (zero - 1) / 2;
  ll p = ms * (ms - 1) / 2 + ps * (ps - 1) / 2;
  assert(m + z + p == n * (n - 1) / 2);

  // cerr << "p: " << p << "\n";
  // cerr << "m: " << m << "\n";
  // cerr << "z: " << z << "\n";
  // cerr << "p + m + z: " << p + m + z << "\n";

  for (auto &&x : {&minus, &plus})
    sort(x->begin(), x->end());

  if (m < k && k <= m + z) {
    cout << 0;
  } else if (k <= m) {
    reverse(plus.begin(), plus.end());
    auto r = bSearch(ll(1e18 + 1), ll(0), [&](ll x) {
      assert(!plus.empty());
      ll result = 0;
      shakutori(
          plus.begin(), plus.end(), minus.begin(), minus.end(),
          [&](auto i, auto j) { return *i * *j < x; },
          [&](auto, auto j) { result += distance(minus.begin(), j); });
      return m - result >= k;
    });
    cout << -r;
  } else {
    auto r = bSearch(ll(0), ll(1e18 + 1), [&](ll x) {
      ll result = 0;
      for (auto con : {&plus, &minus}) {
        shakutori(
            con->rbegin(), con->rend(), con->begin(), con->end(),
            [&](auto i, auto j) { return *i * *j <= x; },
            [&](auto i, auto j) {
              result += distance(con->begin(), j);
              if (*i * *i < x)
                --result;
            });
      }
      assert(result % 2 == 0);
      return result / 2 >= k - z - m;
    });
    cout << r;
  }

  return 0;
}


Fixed submission:
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define for0(i, N) for (int i = 0; i < (N); ++i)
#define for1n(i, N) for (int i = 1; i <= (N); ++i)
#define for1(i, N) for (int i = 1; i < (N); ++i)
#define forn(i, N) for (int i = 0; i <= (N); ++i)
#define forx(i, N, x) for (int i = (x); i < (N); ++i)
#define forl(i, N, x, a)                                                       \
  for (int i = (x), a = 0; a < (N); i = (i + 1) % (N), ++a)

template <size_t i> std::bitset<i> operator++(std::bitset<i> b, int) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  return b = (unsigned long long)b + 1;
}

template <size_t i> std::bitset<i> operator++(std::bitset<i> b) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  auto temp = b;
  b++;
  return temp;
}

template <size_t i> std::bitset<i> operator--(std::bitset<i> b, int) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  return b = (unsigned long long)b - 1;
}

template <size_t i> std::bitset<i> operator--(std::bitset<i> b) {
  static_assert(i <= 64, "Cannot cast 64bit int.");
  auto temp = b;
  b--;
  return temp;
}

using namespace std;

typedef long long ll;
typedef long double ld;
typedef priority_queue<ll> pq;
typedef priority_queue<ll, vector<ll>, greater<ll>> pql;
typedef stack<ll> stk;
typedef queue<ll> qu;
typedef pair<ll, ll> pll;
typedef map<ll, ll> mll;
typedef unordered_map<ll, ll> umll;
typedef set<ll> sll;
typedef unordered_set<ll> usll;
typedef vector<ll> vll;
typedef vector<ld> vld;

// right is true, left is false.
template <class T, class F> T bSearch(T l, T r, F func, T diff = 1) {
  while (std::abs(r - l) > diff) {
    T m = (l + r) / 2;
    (func(m) ? r : l) = m;
  }
  return r;
}

template <class Iterator1, class IteratorDynamic, class Condition, class Func2>
void shakutori(Iterator1 bg1, Iterator1 ed1, IteratorDynamic bg2,
               IteratorDynamic ed2, Condition cond, Func2 func2) {
  auto it2 = bg2;
  for (auto it1 = bg1; it1 != ed1; ++it1) {
    while (it2 != ed2 && cond(it1, it2))
      ++it2;
    func2(it1, it2);
  }
}

int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  ll n, k;
  cin >> n >> k;

  vll minus, plus;
  ll zero = 0;

  for0(i, n) {
    ll a;
    cin >> a;
    if (a > 0) {
      plus.push_back(a);
    } else if (a < 0) {
      minus.push_back(-a);
    } else {
      ++zero;
      assert(a == 0);
    }
  }

  assert(plus.size() + minus.size() + zero == n);
  ll ms = minus.size();
  ll ps = plus.size();

  assert(n * (n - 1) / 2 == ms * ps + ps * zero + zero * ms +
                                zero * (zero - 1) / 2 + ps * (ps - 1) / 2 +
                                ms * (ms - 1) / 2);

  // cerr << "all: "
  //     << ms * ps + ps * zero + zero * ms +
  //     zero * (zero - 1) / 2 + ps *(ps - 1) / 2 + ms *(ms - 1) / 2 << "\n";

  ll m = ms * ps;
  ll z = zero * ps + zero * ms + zero * (zero - 1) / 2;
  ll p = ms * (ms - 1) / 2 + ps * (ps - 1) / 2;
  assert(m + z + p == n * (n - 1) / 2);

  // cerr << "p: " << p << "\n";
  // cerr << "m: " << m << "\n";
  // cerr << "z: " << z << "\n";
  // cerr << "p + m + z: " << p + m + z << "\n";

  for (auto &&x : {&minus, &plus})
    sort(x->begin(), x->end());

  if (m < k && k <= m + z) {
    cout << 0;
  } else if (k <= m) {
    reverse(plus.begin(), plus.end());
    auto r = bSearch(ll(1e18 + 1), ll(0), [&](ll x) {
      assert(!plus.empty());
      ll result = 0;
      shakutori(
          plus.begin(), plus.end(), minus.begin(), minus.end(),
          [&](auto i, auto j) { return *i * *j < x; },
          [&](auto, auto j) { result += distance(minus.begin(), j); });
      return m - result >= k;
    });
    cout << -r;
  } else {
    auto r = bSearch(ll(0), ll(1e18 + 1), [&](ll x) {
      ll result = 0;
      for (auto con : {&plus, &minus}) {
        shakutori(
            con->rbegin(), con->rend(), con->begin(), con->end(),
            [&](auto i, auto j) { return *i * *j <= x; },
            [&](auto i, auto j) {
              result += distance(con->begin(), j);
              if (*i * *i <= x)
                --result;
            });
      }
      assert(result % 2 == 0);
      return result / 2 >= k - z - m;
    });
    cout << r;
  }

  return 0;
}