Problem p02774 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;

long long find_min(function<bool(long long)> solve, long long low,
                   long long high) {
  long long ng = low, ok = high;
  while (ok - ng > 1) {
    long long mid = (ok + ng) / 2;
    if (solve(mid)) {
      ok = mid;
    } else {
      ng = mid;
    }
  }
  return ok;
}

int main() {
  ll n, k, zero = 0;
  cin >> n >> k;
  vector<ll> A_plus, A_minus;
  for (int i = 0; i < n; i++) {
    ll a;
    cin >> a;
    if (a > 0)
      A_plus.push_back(a);
    else if (a < 0)
      A_minus.push_back(-a);
    else
      zero++;
  }
  sort(A_plus.begin(), A_plus.end());
  sort(A_minus.begin(), A_minus.end());
  ll num_minus = A_minus.size() * A_plus.size();
  ll num_zero = zero * (n - zero) + zero * (zero - 1) / 2;
  ll ans;
  if (k <= num_minus) {
    function<ll(ll)> g = [&](ll x) {
      ll res = 0, j = A_minus.size();
      for (ll i : A_plus) {
        while (j > 0 && i * A_minus[j - 1] >= -x)
          j--;
        res += A_minus.size() - j;
      }
      return res;
    };
    function<bool(ll)> f = [&](ll x) { return g(x) >= k; };
    ans = find_min(f, -(*A_minus.rbegin()) * (*A_plus.rbegin()) - 1, -1);
  } else if (k <= num_minus + num_zero) {
    ans = 0;
  } else {
    k -= num_minus + num_zero;
    function<ll(ll)> g = [&](ll x) {
      ll res = 0, j = A_minus.size() - 1;
      for (ll i = 0; i < A_minus.size() && i < j; i++) {
        ll z = x / A_minus[i];
        while (j > i && A_minus[j] > z)
          j--;
        res += j - i;
      }
      j = A_plus.size() - 1;
      for (ll i = 0; i < A_plus.size() && i < j; i++) {
        ll z = x / A_plus[i];
        while (j > i && A_plus[j] > z)
          j--;
        res += j - i;
      }
      return res;
    };
    function<bool(ll)> f = [&](ll x) { return g(x) >= k; };
    ans = find_min(f, 0,
                   max((*A_plus.rbegin()) * (*A_plus.rbegin()),
                       (*A_minus.rbegin()) * (*A_minus.rbegin())) +
                       1);
  }
  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;

long long find_min(function<bool(long long)> solve, long long low,
                   long long high) {
  long long ng = low, ok = high;
  while (ok - ng > 1) {
    long long mid = (ok + ng) / 2;
    if (solve(mid)) {
      ok = mid;
    } else {
      ng = mid;
    }
  }
  return ok;
}

int main() {
  ll n, k, zero = 0;
  cin >> n >> k;
  vector<ll> A_plus, A_minus;
  for (int i = 0; i < n; i++) {
    ll a;
    cin >> a;
    if (a > 0)
      A_plus.push_back(a);
    else if (a < 0)
      A_minus.push_back(-a);
    else
      zero++;
  }
  sort(A_plus.begin(), A_plus.end());
  sort(A_minus.begin(), A_minus.end());
  ll num_minus = A_minus.size() * A_plus.size();
  ll num_zero = zero * (n - zero) + zero * (zero - 1) / 2;
  ll ans;
  if (k <= num_minus) {
    function<ll(ll)> g = [&](ll x) {
      ll res = 0, j = A_minus.size();
      for (ll i : A_plus) {
        while (j > 0 && i * A_minus[j - 1] >= -x)
          j--;
        res += A_minus.size() - j;
      }
      return res;
    };
    function<bool(ll)> f = [&](ll x) { return g(x) >= k; };
    ans = find_min(f, -(*A_minus.rbegin()) * (*A_plus.rbegin()) - 1, -1);
  } else if (k <= num_minus + num_zero) {
    ans = 0;
  } else {
    k -= num_minus + num_zero;
    function<ll(ll)> g = [&](ll x) {
      ll res = 0, j = A_minus.size() - 1;
      for (ll i = 0; i < A_minus.size() && i < j; i++) {
        ll z = x / A_minus[i];
        while (j > i && A_minus[j] > z)
          j--;
        res += j - i;
      }
      j = A_plus.size() - 1;
      for (ll i = 0; i < A_plus.size() && i < j; i++) {
        ll z = x / A_plus[i];
        while (j > i && A_plus[j] > z)
          j--;
        res += j - i;
      }
      return res;
    };
    function<bool(ll)> f = [&](ll x) { return g(x) >= k; };
    ll high = 1;
    if (!A_plus.empty())
      high = max(high, *A_plus.rbegin());
    if (!A_minus.empty())
      high = max(high, *A_minus.rbegin());
    high = high * high + 1;
    ans = find_min(f, 0, high);
  }
  cout << ans << endl;
  return 0;
}