Problem p02616 (C++) — buggy submission, verdict: Runtime Error

#define NDEBUG
NDEBUG

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

template <class T> using vec = std::vector<T>;

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

#define all(c) c.begin(), c.end()

typedef int64_t i64;

// TC_REMOVE_BEGIN
/// caide keep
bool __hack = std::ios::sync_with_stdio(false);
/// caide keep
auto __hack1 = cin.tie(nullptr);
// TC_REMOVE_END

// Section with adoption of array and vector algorithms.

// #include <ext/pb_ds/tree_policy.hpp>
// #include <ext/pb_ds/assoc_container.hpp>
//
// template <class T> using StdTree = tree<T, null_type, less<T>,
// rb_tree_tag,tree_order_statistics_node_update>;

namespace template_util {

constexpr int bytecount(uint64_t x) { return x ? 1 + bytecount(x >> 8) : 0; }

template <int N> struct bytetype {};

/// caide keep
template <uint64_t N> struct minimal_uint : bytetype<bytecount(N)> {};
} // namespace template_util

template <class T> T next(istream &in) {
  T ret;
  in >> ret;
  return ret;
}

#define dbg(...) ;

// m must be positive

template <typename T, typename C, T Modulus> class MR {
private:
  // indicates value is in range [0, 2 * Modulus)
  struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
  struct tag_good {};  // indicates value is in range

  //  T value;

  static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0,
                "compute type is too small");
  static_assert(Modulus < std::numeric_limits<T>::max() / 2,
                "storage type is too small");

  static constexpr T reduce(T value, tag_minus) {
    return value < 0 ? value + Modulus : value;
  }

  static constexpr T reduce(T value, tag_good) { return value; }

public:
  T value;

  constexpr MR(C value) : value(reduce(value % Modulus, tag_minus())) {}
  template <typename tag_t>
  constexpr MR(T value, tag_t tag) : value(reduce(value, tag)) {}

  constexpr MR operator*(MR b) const {
    return MR(C(value) * C(b.value) % Modulus, tag_good());
  }

  MR &operator*=(MR b) {
    value = C(value) * C(b.value) % Modulus;
    return *this;
  }

  constexpr T get() const { return value; }

  // These are only valid if the dividend is relatively prime to the modulus
};

template <typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr) {
  return o << mr.get();
}

typedef MR<int, int64_t, 1000000007> md;

void solve(istream &in, ostream &out) {
  auto n = next<int>(in);
  auto k = next<int>(in);
  int cnt0 = 0;
  vec<i64> positive, negative;
  FOR(i, n) {
    auto x = next<int>(in);
    if (x < 0) {
      negative.push_back(-x);
    } else if (x > 0) {
      positive.push_back(x);
    } else {
      ++cnt0;
    }
  }

  if (cnt0) {
    // NOT this
  }

  if (negative.size() + positive.size() < k) {
    // NOT THIS
    out << "0\\n";
    return;
  }
  sort(all(positive));
  sort(all(negative));

  if (n == k) {
    // NOT THIS
    md res = 1;
    if (cnt0) {
      out << 0 << "\\n";
      return;
    }
    FOR(i, negative.size()) { res *= md(-negative[i]); }
    FOR(i, positive.size()) { res *= md(positive[i]); }
    out << res << "\\n";
    return;
  }
  if (positive.empty()) {
    // NOT this
    if (k % 2 == 0) {
      md res = 1;
      int need = k;
      for (int i = (int)negative.size() - 1; i >= 0 && need; --i) {
        --need;
        res *= md(-negative[i]);
      }
      if (need) {
        out << 0 << "\\n";
        return;
      }
      out << res << "\\n";
      return;
    }
    if (cnt0) {
      out << 0 << "\\n";
      return;
    }
    md res = 1;
    for (int i = 0; i < k; ++i) {
      res *= md(-negative[i]);
    }
    out << res << "\\n";
    return;
  }

  // k % 2 == 0, !cnt0
  if (k % 2 == 0 && !cnt0) {

    //    reverse(all(positive));
    //    reverse(all(negative));
    dbg(positive);
    dbg(negative);
    md res = 1;
    while (k) {

      if (positive.size() >= 2 && negative.size() >= 2) {
        if (positive.back() * positive.end()[-2] <
            negative.back() * negative.end()[-2]) {
          res *= negative.back();
          negative.pop_back();
          res *= negative.back();
          negative.pop_back();
        } else {
          res *= positive.back();
          positive.pop_back();
          res *= positive.back();
          positive.pop_back();
        }
        k -= 2;
        continue;
      }

      if (positive.size() >= 2) {
        res *= positive.back();
        positive.pop_back();
        res *= positive.back();
        positive.pop_back();
      } else {
        res *= negative.back();
        negative.pop_back();
        res *= negative.back();
        negative.pop_back();
      }
      k -= 2;
    }

    out << res << "\\n";
    return;
  }

  long double resMax = -1;
  int resMaxI = -1;
  sort(all(positive));
  sort(all(negative));
  reverse(all(positive));
  reverse(all(negative));
  vec<long double> lgPos, lgNeg;
  lgPos.push_back(0);
  lgNeg.push_back(0);
  FOR(i, positive.size()) {
    lgPos.push_back(lgPos.back() + log2(1. * positive[i]));
  }
  FOR(i, negative.size()) {
    lgNeg.push_back(lgNeg.back() + log2(1. * negative[i]));
  }
  FOR(i, lgPos.size()) {
    int rest = k - i;
    if (rest < 0)
      break;
    if (rest % 2 == 0 && rest <= negative.size()) {
      if (resMax < lgPos[i] + lgNeg[rest] - 1e-15) {
        resMax = lgPos[i] + lgNeg[rest];
        resMaxI = i;
      }
    }
  }
  auto compute = [&](int id) -> md {
    md res = 1;
    FOR(i, id) { res = res * positive[i]; }
    int rest = k - id;
    FOR(i, rest) { res = res * md(-negative[i]); }
    return res;
  };
  if (resMaxI == -1) {
    out << "0\\n";
    return;
  }
  out << compute(resMaxI) << "\\n";
}

// #include <fstream>

int main() {
  //  ifstream fin("bridges.in");
  //  ofstream fout("bridges.out");
  solve(cin, cout);
  //  solve(fin, fout);
  return 0;
}


Error: -6
terminate called after throwing an instance of 'int'


Fixed submission:

#define NDEBUG
NDEBUG

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

template <class T> using vec = std::vector<T>;

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

#define all(c) c.begin(), c.end()

typedef int64_t i64;

// TC_REMOVE_BEGIN
/// caide keep
bool __hack = std::ios::sync_with_stdio(false);
/// caide keep
auto __hack1 = cin.tie(nullptr);
// TC_REMOVE_END

// Section with adoption of array and vector algorithms.

// #include <ext/pb_ds/tree_policy.hpp>
// #include <ext/pb_ds/assoc_container.hpp>
//
// template <class T> using StdTree = tree<T, null_type, less<T>,
// rb_tree_tag,tree_order_statistics_node_update>;

namespace template_util {

constexpr int bytecount(uint64_t x) { return x ? 1 + bytecount(x >> 8) : 0; }

template <int N> struct bytetype {};

/// caide keep
template <uint64_t N> struct minimal_uint : bytetype<bytecount(N)> {};
} // namespace template_util

template <class T> T next(istream &in) {
  T ret;
  in >> ret;
  return ret;
}

// m must be positive

template <typename T, typename C, T Modulus> class MR {
private:
  // indicates value is in range [0, 2 * Modulus)
  struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
  struct tag_good {};  // indicates value is in range

  //  T value;

  static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0,
                "compute type is too small");
  static_assert(Modulus < std::numeric_limits<T>::max() / 2,
                "storage type is too small");

  static constexpr T reduce(T value, tag_minus) {
    return value < 0 ? value + Modulus : value;
  }

  static constexpr T reduce(T value, tag_good) { return value; }

public:
  T value;

  constexpr MR(C value) : value(reduce(value % Modulus, tag_minus())) {}
  template <typename tag_t>
  constexpr MR(T value, tag_t tag) : value(reduce(value, tag)) {}

  constexpr MR operator*(MR b) const {
    return MR(C(value) * C(b.value) % Modulus, tag_good());
  }

  MR &operator*=(MR b) {
    value = C(value) * C(b.value) % Modulus;
    return *this;
  }

  constexpr T get() const { return value; }

  // These are only valid if the dividend is relatively prime to the modulus
};

template <typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr) {
  return o << mr.get();
}

typedef MR<int, int64_t, 1000000007> md;

void solve(istream &in, ostream &out) {
  auto n = next<int>(in);
  auto k = next<int>(in);
  int cnt0 = 0;
  vec<i64> positive, negative;
  FOR(i, n) {
    auto x = next<int>(in);
    if (x < 0) {
      negative.push_back(-x);
    } else if (x > 0) {
      positive.push_back(x);
    } else {
      ++cnt0;
    }
  }

  if (cnt0) {
    // NOT this
  }

  if (negative.size() + positive.size() < k) {
    // NOT THIS
    out << "0\\n";
    return;
  }
  sort(all(positive));
  sort(all(negative));

  if (n == k) {
    // NOT THIS
    md res = 1;
    if (cnt0) {
      out << 0 << "\\n";
      return;
    }
    FOR(i, negative.size()) { res *= md(-negative[i]); }
    FOR(i, positive.size()) { res *= md(positive[i]); }
    out << res << "\\n";
    return;
  }
  if (positive.empty()) {
    // NOT this
    if (k % 2 == 0) {
      md res = 1;
      int need = k;
      for (int i = (int)negative.size() - 1; i >= 0 && need; --i) {
        --need;
        res *= md(-negative[i]);
      }
      if (need) {
        out << 0 << "\\n";
        return;
      }
      out << res << "\\n";
      return;
    }
    if (cnt0) {
      out << 0 << "\\n";
      return;
    }
    md res = 1;
    for (int i = 0; i < k; ++i) {
      res *= md(-negative[i]);
    }
    out << res << "\\n";
    return;
  }

  if (k % 2 == 0) {
    throw 42;
  } else {
    while (1)
      ;
  }

  long double resMax = -1;
  int resMaxI = -1;
  sort(all(positive));
  sort(all(negative));
  reverse(all(positive));
  reverse(all(negative));
  vec<long double> lgPos, lgNeg;
  lgPos.push_back(0);
  lgNeg.push_back(0);
  FOR(i, positive.size()) {
    lgPos.push_back(lgPos.back() + log2(1. * positive[i]));
  }
  FOR(i, negative.size()) {
    lgNeg.push_back(lgNeg.back() + log2(1. * negative[i]));
  }
  FOR(i, lgPos.size()) {
    int rest = k - i;
    if (rest < 0)
      break;
    if (rest % 2 == 0 && rest <= negative.size()) {
      if (resMax < lgPos[i] + lgNeg[rest] - 1e-10) {
        resMax = lgPos[i] + lgNeg[rest];
        resMaxI = i;
      }
    }
  }
  auto compute = [&](int id) -> md {
    md res = 1;
    FOR(i, id) { res = res * positive[i]; }
    int rest = k - id;
    FOR(i, rest) { res = res * md(-negative[i]); }
    return res;
  };
  if (resMaxI == -1) {
    out << "0\\n";
    return;
  }
  out << compute(resMaxI) << "\\n";
}

// #include <fstream>

int main() {
  //  ifstream fin("bridges.in");
  //  ofstream fout("bridges.out");
  solve(cin, cout);
  //  solve(fin, fout);
  return 0;
}