Problem p02774 (C++)

Buggy submission (status: Runtime Error):
//----------------------------templates
#pragma GCC optimize("Ofast")
#pragma GCC target("tune=native")
#pragma GCC target("avx")
//----------------------------
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define int ll

#define FOR(i, j, n) for (int i = (int)(j); i < (n); i++)
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define REPS(i, n) for (int i = 1; i <= (int)(n); i++)
#define REPN(i, n) for (int i = (int)(n)-1; i >= 0; i--)
#define REPNS(i, n) for (int i = (int)(n); i > 0; i--)

#define I(n) scanf("%lld", &(n))
#define LL(n) scanf("%lld", &(n))
#define pb(n) push_back((n))
#define mp(i, j) make_pair((i), (j))
#define eb(i, j) emplace_back((i), (j))
#define y0 y3487465
#define y1 y8687969
#define j0 j1347829
#define j1 j234892
#define uniq(v) v.erase(unique(v.begin(), v.end()), v.end())

#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

typedef vector<int> vi;
typedef pair<int, int> pi;
typedef vector<pi> vpi;
typedef vector<vi> vvi;
typedef vector<vpi> vvpi;
typedef vector<vvi> vvvi;

const int mod = 1000000007;

//--------------------------------------------

int n, k, ai;
int zero;
vi posi, nega;
signed main() {
  I(n);
  I(k);
  REP(i, n) {
    I(ai);
    if (ai == 0)
      zero++;
    if (ai < 0)
      nega.pb(ai);
    if (ai > 0)
      posi.pb(ai);
  }
  sort(all(posi));                 //  1, 2, 3, ...
  sort(all(nega), greater<int>()); // -1,-2,-3, ...

  int nposi = sz(posi);
  int nnega = sz(nega);

  int npnega = sz(posi) * sz(nega);
  int npzero = zero * (sz(posi) + sz(nega)) + zero * (zero - 1) / 2;
  int npposi = nposi * (nposi - 1) / 2 + nnega * (nnega - 1) / 2;
  assert(n * (n - 1) / 2 == npnega + npzero + npposi);

  cerr << nposi << " " << nnega << endl;
  cerr << npnega << " " << npzero << " " << npposi << endl;

  if (k <= npnega) {
    int lo = posi[nposi - 1] * nega[nnega - 1] - 1;
    int hi = posi[0] * nega[0] + 1;
    while (abs(lo - hi) > 1) {
      int mid = abs(lo + hi) / 2 * -1;
      int hit = 0;
      for (auto i : nega) {
        hit += posi.end() - lower_bound(all(posi), (mid - abs(i) + 1) / i);
      }
      cerr << "mid " << mid << " , hit " << hit << endl;

      (hit < k ? lo : hi) = mid;
    }
    cout << hi << endl;
    return 0;
  }
  k -= npnega;
  if (k <= npzero) {
    cout << 0 << endl;
    return 0;
  }
  k -= npzero;
  REP(i, nnega) nega[i] *= -1; // 1, 2, 3 ...
  int lo = 0;
  int hi = 1;
  if (nposi)
    hi += posi[nposi - 1];
  if (nnega)
    hi += posi[nnega - 1];
  hi *= hi;
  while (hi - lo > 1) {
    int mid = (lo + hi) / 2;
    int hit = 0;
    if (nposi > 1)
      REP(ind, nposi) {
        int i = posi[ind];
        int cand = upper_bound(posi.begin(), posi.begin() + ind, mid / i) -
                   posi.begin();
        hit += cand;
      }
    if (nnega > 1)
      REP(ind, nnega) {
        int i = nega[ind];
        int cand = upper_bound(nega.begin(), nega.begin() + ind, mid / i) -
                   nega.begin();
        hit += cand;
      }
    cerr << "mid " << mid << " , hit " << hit << endl;
    (hit < k ? lo : hi) = mid;
  }
  cout << hi << endl;
}

Fixed submission:
//----------------------------templates
#pragma GCC optimize("Ofast")
#pragma GCC target("tune=native")
#pragma GCC target("avx")
//----------------------------
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define int ll

#define FOR(i, j, n) for (int i = (int)(j); i < (n); i++)
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define REPS(i, n) for (int i = 1; i <= (int)(n); i++)
#define REPN(i, n) for (int i = (int)(n)-1; i >= 0; i--)
#define REPNS(i, n) for (int i = (int)(n); i > 0; i--)

#define I(n) scanf("%lld", &(n))
#define LL(n) scanf("%lld", &(n))
#define pb(n) push_back((n))
#define mp(i, j) make_pair((i), (j))
#define eb(i, j) emplace_back((i), (j))
#define y0 y3487465
#define y1 y8687969
#define j0 j1347829
#define j1 j234892
#define uniq(v) v.erase(unique(v.begin(), v.end()), v.end())

#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

typedef vector<int> vi;
typedef pair<int, int> pi;
typedef vector<pi> vpi;
typedef vector<vi> vvi;
typedef vector<vpi> vvpi;
typedef vector<vvi> vvvi;

const int mod = 1000000007;

//--------------------------------------------

int n, k, ai;
int zero;
vi posi, nega;
signed main() {
  I(n);
  I(k);
  REP(i, n) {
    I(ai);
    if (ai == 0)
      zero++;
    if (ai < 0)
      nega.pb(ai);
    if (ai > 0)
      posi.pb(ai);
  }
  sort(all(posi));                 //  1, 2, 3, ...
  sort(all(nega), greater<int>()); // -1,-2,-3, ...

  int nposi = sz(posi);
  int nnega = sz(nega);

  int npnega = sz(posi) * sz(nega);
  int npzero = zero * (sz(posi) + sz(nega)) + zero * (zero - 1) / 2;
  int npposi = nposi * (nposi - 1) / 2 + nnega * (nnega - 1) / 2;
  assert(n * (n - 1) / 2 == npnega + npzero + npposi);

  cerr << nposi << " " << nnega << endl;
  cerr << npnega << " " << npzero << " " << npposi << endl;

  if (k <= npnega) {
    int lo = posi[nposi - 1] * nega[nnega - 1] - 1;
    int hi = posi[0] * nega[0] + 1;
    while (abs(lo - hi) > 1) {
      int mid = abs(lo + hi) / 2 * -1;
      int hit = 0;
      for (auto i : nega) {
        hit += posi.end() - lower_bound(all(posi), (mid - abs(i) + 1) / i);
      }
      cerr << "mid " << mid << " , hit " << hit << endl;

      (hit < k ? lo : hi) = mid;
    }
    cout << hi << endl;
    return 0;
  }
  k -= npnega;
  if (k <= npzero) {
    cout << 0 << endl;
    return 0;
  }
  k -= npzero;
  REP(i, nnega) nega[i] *= -1; // 1, 2, 3 ...
  int lo = 0;
  int hi = 1;
  int adder = 1;
  if (nposi > 1)
    adder = max(adder, posi[nposi - 1]);
  if (nnega > 1)
    adder = max(adder, nega[nnega - 1]);
  hi += adder;
  hi *= hi;
  while (hi - lo > 1) {
    int mid = (lo + hi) / 2;
    int hit = 0;
    if (nposi > 1)
      REP(ind, nposi) {
        int i = posi[ind];
        int cand = upper_bound(posi.begin(), posi.begin() + ind, mid / i) -
                   posi.begin();
        hit += cand;
      }
    if (nnega > 1)
      REP(ind, nnega) {
        int i = nega[ind];
        int cand = upper_bound(nega.begin(), nega.begin() + ind, mid / i) -
                   nega.begin();
        hit += cand;
      }
    cerr << "mid " << mid << " , hit " << hit << endl;
    (hit < k ? lo : hi) = mid;
  }
  cout << hi << endl;
}