Problem p02774 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <tuple>
#include <vector>

constexpr long long int inf = 1e18 + 334 + 810 + 1919;

namespace MyInputAndOutput {
// 入力関係 (cin)
class user_input {
public:
  inline const user_input &operator>>(int &int_arg) const {
    scanf("%d", &int_arg);
    return *this;
  }
  inline const user_input &operator>>(long long int &llint_arg) const {
    scanf("%lld", &llint_arg);
    return *this;
  }
  inline const user_input &operator>>(unsigned int &uint_arg) const {
    scanf("%u", &uint_arg);
    return *this;
  }
  inline const user_input &
  operator>>(unsigned long long int &ullint_arg) const {
    scanf("%llu", &ullint_arg);
    return *this;
  }
  inline const user_input &operator>>(unsigned long &ullint_arg) const {
    scanf("%lu", &ullint_arg);
    return *this;
  }
  inline const user_input &operator>>(char *str_arg) const {
    scanf("%s", str_arg);
    return *this;
  }
  inline const user_input &operator>>(char &char_arg) const {
    scanf("%*c%c", &char_arg);
    return *this;
  }
  template <typename S, typename T>
  inline const user_input &operator>>(std::pair<S, T> &pair_arg) const {
    (*this) >> pair_arg.first >> pair_arg.second;
    return *this;
  }
  template <typename T>
  inline const user_input &operator>>(std::vector<T> &vec) const {
    for (T &ele : vec)
      (*this) >> ele;
    return *this;
  }
} cin;

// 出力関係 (cout)
class user_output {
public:
  user_output(void) {}
  inline const user_output &operator<<(const int int_arg) const {
    printf("%d", int_arg);
    return *this;
  }
  inline const user_output &operator<<(const unsigned int uint_arg) const {
    printf("%u", uint_arg);
    return *this;
  }
  inline const user_output &operator<<(const long long int llint_arg) const {
    printf("%lld", llint_arg);
    return *this;
  }
  inline const user_output &
  operator<<(const unsigned long long int ullint_arg) const {
    printf("%llu", ullint_arg);
    return *this;
  }
  inline const user_output &operator<<(const unsigned long ulint_arg) const {
    printf("%lu", ulint_arg);
    return *this;
  }
  inline const user_output &operator<<(const double ld_arg) const {
    printf("%.16lf", ld_arg);
    return *this;
  }
  inline const user_output &operator<<(const long double ld_arg) const {
    printf("%.16Lf", ld_arg);
    return *this;
  }
  inline const user_output &operator<<(const char char_arg) const {
    putchar(char_arg);
    return *this;
  }
  inline const user_output &operator<<(const unsigned char uchar_arg) const {
    putchar(uchar_arg);
    return *this;
  }
  inline const user_output &operator<<(const char *str_arg) const {
    fputs(str_arg, stdout);
    return *this;
  }
  template <typename S, typename T>
  inline const user_output &operator<<(const std::pair<S, T> &pair_arg) const {
    (*this) << pair_arg.first << ' ' << pair_arg.second;
    return *this;
  }
  template <typename Tp_name>
  inline const user_output &operator<<(const std::vector<Tp_name> &vec) const {
    const size_t size_of_vec = vec.size();
    if (size_of_vec <= 0)
      return *this;
    (*this) << vec[0];
    for (size_t index = 1; index < size_of_vec; ++index)
      (*this) << ' ' << vec[index];
    return *this;
  }
} cout;

// その他出力関数
void binary_output(int64_t value, size_t length = 64) {
  char out[length + 1];
  for (size_t i = 0; i < length; ++i)
    out[length - 1 - i] = ((value >> i) & 1) ? '1' : '0';
  out[length] = '\0';
  puts(out);
}
template <typename InputType>
void print(InputType first, InputType last, const char separate_c = ' ',
           const char end_c = '\n') {
  InputType it = first;
  while (true) {
    MyInputAndOutput::cout << *it;
    if (++it == last) {
      MyInputAndOutput::cout << end_c;
      return;
    }
    MyInputAndOutput::cout << separate_c;
  }
}
}; // namespace MyInputAndOutput
namespace MIO = MyInputAndOutput;

// 大小関係のある配列について, 個数を数える |
// クエリ形式の場合はクエリ先読みBITを使え
template <typename element_type> class CountingVector {
private:
  unsigned int size_of_vec; // 座圧済み配列の長さ
  const unsigned int
      size_of_arg_vec; // 元の引数の配列の長さ | = counter[size_of_vec-1]
  std::vector<element_type> vec;     // ソート & 座標圧縮 済み配列
  std::vector<unsigned int> counter; // 累積和 counter[i] = vec[0, i)の数

  using const_itr_type = typename std::vector<element_type>::const_iterator;

public:
  // コンストラクタ : 破壊的操作を行うので引数はコピー
  template <typename element_type_castable>
  CountingVector(std::vector<element_type_castable> arg_vec)
      : size_of_arg_vec(arg_vec.size()) {
    const unsigned int arg_size = arg_vec.size();
    counter.reserve(arg_size + 1);
    counter.push_back(0);
    vec.reserve(arg_size);
    std::sort(arg_vec.begin(), arg_vec.end());
    unsigned int idx = 0;
    while (idx < arg_size) {
      unsigned int cnt = 1;
      vec.push_back(arg_vec[idx]);
      while (idx + cnt < arg_size and arg_vec[idx] == arg_vec[idx + cnt])
        cnt++;
      unsigned int p = counter.back() + cnt;
      counter.push_back(p);
      idx += cnt;
    }
    size_of_vec = vec.size();
  }

  // arg_vec[i] < val なる i の個数を数える
  inline unsigned int
  count_smallerThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return counter[idx];
  }
  inline unsigned int
  count_smallerThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return counter[idx];
  }

  // arg_vec[i] ≤ val なる i の個数を数える
  inline unsigned int
  count_notGreaterThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::upper_bound(vec.begin(), vec.end(), val) - vec.begin();
    return counter[idx];
  }
  inline unsigned int
  count_notGreaterThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return counter[idx + 1];
  }

  // arg_vec[i] > val なる i の個数を数える
  inline unsigned int
  count_greaterThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::upper_bound(vec.begin(), vec.end(), val) - vec.begin();
    return size_of_arg_vec - counter[idx];
  }
  inline unsigned int
  count_greaterThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return size_of_arg_vec - counter[idx + 1];
  }

  // arg_vec[i] ≥ val なる i の個数を数える
  inline unsigned int
  count_notSmallerThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return size_of_arg_vec - counter[idx];
  }
  inline unsigned int
  count_notSmallerThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return size_of_arg_vec - counter[idx];
  }

  // vec[idx] = val なる idx を返す (存在しない場合は -1を返す)
  inline int key(const element_type &val) const noexcept {
    int idx = std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return (vec[idx] == val) ? idx : -1;
  }
  inline int key(const const_itr_type &itr) const noexcept {
    return itr - vec.cbegin();
  }

  // arg_vec[i] = val なる i の個数を数える (存在しないなら 0)
  inline unsigned int count(const element_type &val) const noexcept {
    unsigned int idx =
        std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return (vec[idx] == val) ? counter[idx + 1] - counter[idx] : 0;
  }
  inline unsigned int count(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return counter[idx + 1] - counter[idx];
  }

  // lower_bound, upper_bound
  inline const_itr_type lower_bound(const element_type &val) const noexcept {
    return std::lower_bound(vec.cbegin(), vec.cend(), val);
  }
  inline const_itr_type upper_bound(const element_type &val) const noexcept {
    return std::upper_bound(vec.cbegin(), vec.cend(), val);
  }

  // イテレーター関係
  const_itr_type cbegin(void) const noexcept { return vec.cbegin(); }
  const_itr_type cend(void) const noexcept { return vec.cend(); }
};

int main(void) {
  int n;
  long long int k;
  MIO::cin >> n >> k;
  std::vector<int> Pos, Neg;
  Pos.reserve(n);
  Neg.reserve(n);
  unsigned long long zero = 0;
  for (int i = 0; i < n; ++i) {
    int a;
    MIO::cin >> a;
    if (a < 0)
      Neg.push_back(-a);
    else if (a == 0)
      zero++;
    else
      Pos.push_back(a);
  }
  CountingVector<long long int> CNeg(Neg), CPos(Pos);

  unsigned long long pos = Pos.size(), neg = Neg.size();
  if (k <= pos * neg) {
    long long int ok = 0, ng = inf;
    while (ng - ok > 1) {
      long long int num = (ok + ng) / 2;
      long long int cnt = 0;
      // Ai * (-Aj) ≤ -num -> Ai * Aj ≥ num
      for (auto itr = CPos.cbegin(); itr != CPos.cend(); ++itr) {
        long long int need = num / *itr;
        if (num % (*itr) != 0)
          need++;
        cnt += CNeg.count_notSmallerThan(need) * CPos.count(itr);
        if (cnt >= k)
          break;
      }
      if (cnt >= k)
        ok = num;
      else
        ng = num;
    }
    MIO::cout << -ok << '\n';
    return 0;
  }
  k -= pos * neg;
  if (k <= (pos + neg) * zero + zero * (zero - 1) / 2) {
    MIO::cout << "0\n";
    return 0;
  }
  k -= (pos + neg) * zero + zero * (zero - 1) / 2;

  long long int ok = inf, ng = 0;
  while (ok - ng > 1) {
    long long int num = (ok + ng) / 2;
    long long int cnt = 0;

    // ai * aj ≤ num : ai ≤ (num / aj)
    for (auto itr = CNeg.cbegin(); itr != CNeg.cend(); ++itr) {
      long long int need = num / *itr;
      long long int kazu = CNeg.count(itr);
      const auto itr2 = CNeg.upper_bound(need);
      if (itr < itr2) {
        cnt += CNeg.count_smallerThan(itr) * kazu;
        cnt += kazu * (kazu - 1) / 2;
      } else
        cnt += CNeg.count_smallerThan(itr2) * kazu;
      if (cnt >= k)
        break;
    }
    for (auto itr = CPos.cbegin(); itr != CPos.cend(); ++itr) {
      long long int need = num / *itr;
      long long int kazu = CNeg.count(itr);
      const auto itr2 = CPos.upper_bound(need);
      if (itr < itr2) {
        cnt += CPos.count_smallerThan(itr) * kazu;
        cnt += kazu * (kazu - 1) / 2;
      } else
        cnt += CPos.count_smallerThan(itr2) * kazu;
      if (cnt >= k)
        break;
    }
    if (cnt >= k)
      ok = num;
    else
      ng = num;
  }
  MIO::cout << ok << '\n';
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cstdio>
#include <tuple>
#include <vector>

constexpr long long int inf = 1e18 + 334 + 810 + 1919;

namespace MyInputAndOutput {
// 入力関係 (cin)
class user_input {
public:
  inline const user_input &operator>>(int &int_arg) const {
    scanf("%d", &int_arg);
    return *this;
  }
  inline const user_input &operator>>(long long int &llint_arg) const {
    scanf("%lld", &llint_arg);
    return *this;
  }
  inline const user_input &operator>>(unsigned int &uint_arg) const {
    scanf("%u", &uint_arg);
    return *this;
  }
  inline const user_input &
  operator>>(unsigned long long int &ullint_arg) const {
    scanf("%llu", &ullint_arg);
    return *this;
  }
  inline const user_input &operator>>(unsigned long &ullint_arg) const {
    scanf("%lu", &ullint_arg);
    return *this;
  }
  inline const user_input &operator>>(char *str_arg) const {
    scanf("%s", str_arg);
    return *this;
  }
  inline const user_input &operator>>(char &char_arg) const {
    scanf("%*c%c", &char_arg);
    return *this;
  }
  template <typename S, typename T>
  inline const user_input &operator>>(std::pair<S, T> &pair_arg) const {
    (*this) >> pair_arg.first >> pair_arg.second;
    return *this;
  }
  template <typename T>
  inline const user_input &operator>>(std::vector<T> &vec) const {
    for (T &ele : vec)
      (*this) >> ele;
    return *this;
  }
} cin;

// 出力関係 (cout)
class user_output {
public:
  user_output(void) {}
  inline const user_output &operator<<(const int int_arg) const {
    printf("%d", int_arg);
    return *this;
  }
  inline const user_output &operator<<(const unsigned int uint_arg) const {
    printf("%u", uint_arg);
    return *this;
  }
  inline const user_output &operator<<(const long long int llint_arg) const {
    printf("%lld", llint_arg);
    return *this;
  }
  inline const user_output &
  operator<<(const unsigned long long int ullint_arg) const {
    printf("%llu", ullint_arg);
    return *this;
  }
  inline const user_output &operator<<(const unsigned long ulint_arg) const {
    printf("%lu", ulint_arg);
    return *this;
  }
  inline const user_output &operator<<(const double ld_arg) const {
    printf("%.16lf", ld_arg);
    return *this;
  }
  inline const user_output &operator<<(const long double ld_arg) const {
    printf("%.16Lf", ld_arg);
    return *this;
  }
  inline const user_output &operator<<(const char char_arg) const {
    putchar(char_arg);
    return *this;
  }
  inline const user_output &operator<<(const unsigned char uchar_arg) const {
    putchar(uchar_arg);
    return *this;
  }
  inline const user_output &operator<<(const char *str_arg) const {
    fputs(str_arg, stdout);
    return *this;
  }
  template <typename S, typename T>
  inline const user_output &operator<<(const std::pair<S, T> &pair_arg) const {
    (*this) << pair_arg.first << ' ' << pair_arg.second;
    return *this;
  }
  template <typename Tp_name>
  inline const user_output &operator<<(const std::vector<Tp_name> &vec) const {
    const size_t size_of_vec = vec.size();
    if (size_of_vec <= 0)
      return *this;
    (*this) << vec[0];
    for (size_t index = 1; index < size_of_vec; ++index)
      (*this) << ' ' << vec[index];
    return *this;
  }
} cout;

// その他出力関数
void binary_output(int64_t value, size_t length = 64) {
  char out[length + 1];
  for (size_t i = 0; i < length; ++i)
    out[length - 1 - i] = ((value >> i) & 1) ? '1' : '0';
  out[length] = '\0';
  puts(out);
}
template <typename InputType>
void print(InputType first, InputType last, const char separate_c = ' ',
           const char end_c = '\n') {
  InputType it = first;
  while (true) {
    MyInputAndOutput::cout << *it;
    if (++it == last) {
      MyInputAndOutput::cout << end_c;
      return;
    }
    MyInputAndOutput::cout << separate_c;
  }
}
}; // namespace MyInputAndOutput
namespace MIO = MyInputAndOutput;

// 大小関係のある配列について, 個数を数える |
// クエリ形式の場合はクエリ先読みBITを使え
template <typename element_type> class CountingVector {
private:
  unsigned int size_of_vec; // 座圧済み配列の長さ
  const unsigned int
      size_of_arg_vec; // 元の引数の配列の長さ | = counter[size_of_vec-1]
  std::vector<element_type> vec;     // ソート & 座標圧縮 済み配列
  std::vector<unsigned int> counter; // 累積和 counter[i] = vec[0, i)の数

  using const_itr_type = typename std::vector<element_type>::const_iterator;

public:
  // コンストラクタ : 破壊的操作を行うので引数はコピー
  template <typename element_type_castable>
  CountingVector(std::vector<element_type_castable> arg_vec)
      : size_of_arg_vec(arg_vec.size()) {
    const unsigned int arg_size = arg_vec.size();
    counter.reserve(arg_size + 1);
    counter.push_back(0);
    vec.reserve(arg_size);
    std::sort(arg_vec.begin(), arg_vec.end());
    unsigned int idx = 0;
    while (idx < arg_size) {
      unsigned int cnt = 1;
      vec.push_back(arg_vec[idx]);
      while (idx + cnt < arg_size and arg_vec[idx] == arg_vec[idx + cnt])
        cnt++;
      unsigned int p = counter.back() + cnt;
      counter.push_back(p);
      idx += cnt;
    }
    size_of_vec = vec.size();
  }

  // arg_vec[i] < val なる i の個数を数える
  inline unsigned int
  count_smallerThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return counter[idx];
  }
  inline unsigned int
  count_smallerThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return counter[idx];
  }

  // arg_vec[i] ≤ val なる i の個数を数える
  inline unsigned int
  count_notGreaterThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::upper_bound(vec.begin(), vec.end(), val) - vec.begin();
    return counter[idx];
  }
  inline unsigned int
  count_notGreaterThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return counter[idx + 1];
  }

  // arg_vec[i] > val なる i の個数を数える
  inline unsigned int
  count_greaterThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::upper_bound(vec.begin(), vec.end(), val) - vec.begin();
    return size_of_arg_vec - counter[idx];
  }
  inline unsigned int
  count_greaterThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return size_of_arg_vec - counter[idx + 1];
  }

  // arg_vec[i] ≥ val なる i の個数を数える
  inline unsigned int
  count_notSmallerThan(const element_type &val) const noexcept {
    unsigned int idx =
        std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return size_of_arg_vec - counter[idx];
  }
  inline unsigned int
  count_notSmallerThan(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return size_of_arg_vec - counter[idx];
  }

  // vec[idx] = val なる idx を返す (存在しない場合は -1を返す)
  inline int key(const element_type &val) const noexcept {
    int idx = std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return (vec[idx] == val) ? idx : -1;
  }
  inline int key(const const_itr_type &itr) const noexcept {
    return itr - vec.cbegin();
  }

  // arg_vec[i] = val なる i の個数を数える (存在しないなら 0)
  inline unsigned int count(const element_type &val) const noexcept {
    unsigned int idx =
        std::lower_bound(vec.begin(), vec.end(), val) - vec.begin();
    return (vec[idx] == val) ? counter[idx + 1] - counter[idx] : 0;
  }
  inline unsigned int count(const const_itr_type &itr) const noexcept {
    unsigned int idx = itr - vec.cbegin();
    return counter[idx + 1] - counter[idx];
  }

  // lower_bound, upper_bound
  inline const_itr_type lower_bound(const element_type &val) const noexcept {
    return std::lower_bound(vec.cbegin(), vec.cend(), val);
  }
  inline const_itr_type upper_bound(const element_type &val) const noexcept {
    return std::upper_bound(vec.cbegin(), vec.cend(), val);
  }

  // イテレーター関係
  const_itr_type cbegin(void) const noexcept { return vec.cbegin(); }
  const_itr_type cend(void) const noexcept { return vec.cend(); }
};

int main(void) {
  int n;
  long long int k;
  MIO::cin >> n >> k;
  std::vector<int> Pos, Neg;
  Pos.reserve(n);
  Neg.reserve(n);
  unsigned long long zero = 0;
  for (int i = 0; i < n; ++i) {
    int a;
    MIO::cin >> a;
    if (a < 0)
      Neg.push_back(-a);
    else if (a == 0)
      zero++;
    else
      Pos.push_back(a);
  }
  CountingVector<long long int> CNeg(Neg), CPos(Pos);

  unsigned long long pos = Pos.size(), neg = Neg.size();
  if (k <= pos * neg) {
    long long int ok = 0, ng = inf;
    while (ng - ok > 1) {
      long long int num = (ok + ng) / 2;
      long long int cnt = 0;
      // Ai * (-Aj) ≤ -num -> Ai * Aj ≥ num
      for (auto itr = CPos.cbegin(); itr != CPos.cend(); ++itr) {
        long long int need = num / *itr;
        if (num % (*itr) != 0)
          need++;
        cnt += CNeg.count_notSmallerThan(need) * CPos.count(itr);
        if (cnt >= k)
          break;
      }
      if (cnt >= k)
        ok = num;
      else
        ng = num;
    }
    MIO::cout << -ok << '\n';
    return 0;
  }
  k -= pos * neg;
  if (k <= (pos + neg) * zero + zero * (zero - 1) / 2) {
    MIO::cout << "0\n";
    return 0;
  }
  k -= (pos + neg) * zero + zero * (zero - 1) / 2;

  long long int ok = inf, ng = 0;
  while (ok - ng > 1) {
    long long int num = (ok + ng) / 2;
    long long int cnt = 0;

    // ai * aj ≤ num : ai ≤ (num / aj)
    for (auto itr = CNeg.cbegin(); itr != CNeg.cend(); ++itr) {
      long long int need = num / *itr;
      long long int kazu = CNeg.count(itr);
      const auto itr2 = CNeg.upper_bound(need);
      if (itr < itr2) {
        cnt += CNeg.count_smallerThan(itr) * kazu;
        cnt += kazu * (kazu - 1) / 2;
      } else
        cnt += CNeg.count_smallerThan(itr2) * kazu;
      if (cnt >= k)
        break;
    }
    for (auto itr = CPos.cbegin(); itr != CPos.cend(); ++itr) {
      long long int need = num / *itr;
      long long int kazu = CPos.count(itr);
      const auto itr2 = CPos.upper_bound(need);
      if (itr < itr2) {
        cnt += CPos.count_smallerThan(itr) * kazu;
        cnt += kazu * (kazu - 1) / 2;
      } else
        cnt += CPos.count_smallerThan(itr2) * kazu;
      if (cnt >= k)
        break;
    }
    if (cnt >= k)
      ok = num;
    else
      ng = num;
  }
  MIO::cout << ok << '\n';
  return 0;
}