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

#include "bits/stdc++.h"
using namespace std;
typedef long long ll;

template <typename TYPE> void print_vec(const vector<TYPE> &v) {
  for (int i = 0; i < v.size(); i++) {
    cout << v[i] << " ";
  }
  cout << endl;
}

template <typename TYPE> void print_vec2(const vector<vector<TYPE>> &v) {
  cout << endl;
  cout << "       ";
  for (int i = 0; i < v[0].size(); i++)
    cout << i << "   ";
  cout << endl;
  for (int i = 0; i < v.size(); i++) {
    cout << "i=" << i << ":   ";
    for (int j = 0; j < v[i].size(); j++) {
      if (v[i][j] == 0)
        cout << "\\x1B[0m" << v[i][j] << "   ";
      else
        cout << "\\x1B[31m" << v[i][j]
             << "   "; // https://stackoverrun.com/ja/q/12618775
    }
    cout << "\\x1B[0m" << endl;
  }
}

// https://github.com/atcoder-live/library/blob/master/mint.cpp
//  auto mod int
//  https://youtu.be/L8grWxBlIZ4?t=9858
//  https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
//  https://youtu.be/8uowVvQ_-Mo?t=1329 : division
const int mod = 1000000007;
// const int mod = 998244353;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }

int main() {
  int N, K;
  cin >> N >> K;
  vector<ll> A(N);
  for (int i = 0; i < N; i++)
    cin >> A[i];

  typedef pair<ll, int> p;
  // second: -1ならA[i]がマイナス, 1ならA[i]0以上
  vector<p> vec;
  for (int i = 0; i < N; i++) {
    if (A[i] >= 0)
      vec.emplace_back(A[i], 1);
    else
      vec.emplace_back(-1 * A[i], -1);
  }

  sort(vec.rbegin(), vec.rend()); // 絶対値の大きいモノを前に持ってくる

  ////////////////////////////
  // 以下解法見た
  int num_plus = 0;
  int num_minus = 0;
  for (int i = 0; i < N; i++) {
    if (A[i] >= 0)
      num_plus++;
    else
      num_minus++;
  }
  if ((num_plus == 0 && K % 2 == 1) || N == K) {
    // 答えを正にできない場合
    //(N==Kは選ぶ余地がないときです.
    // A[i]に正の数があっても 選ぶ余地がないと
    // 負になる場合があるから　処理しておく)
    mint ans(1);
    for (int i = 0; i < K; i++) {
      ans *= vec[N - 1 - i].first * vec[N - 1 - i].second;
    }
    cout << ans.x << endl;
    return 0;
  }

  vector<ll> plus;
  vector<ll> minus;
  for (int i = 0; i < N; i++) {
    if (A[i] >= 0)
      plus.push_back(A[i]);
    else
      minus.push_back(A[i]);
  }

  sort(plus.begin(), plus.end()); // 絶対値が大きいのを後ろにもってくる
  sort(minus.rbegin(), minus.rend()); // 絶対値が大きいのを後ろに持ってくる

  mint ans(1);
  if (K % 2 == 1) {
    ans *= plus.back();
    plus.pop_back();
    K--;
  }

  for (int i = 0; i < K; i = i + 2) {
    // if(num_plus<2 && num_minus<2){
    // 	// N==K のときありうるのかな?
    // 	// これのとき
    // 	//必ずnum_plus = num_minus = 1となってるのかな
    // 	ans *= minus.back();
    // 	ans *= plus.back();
    // 	minus.pop_back();
    // 	plus.pop_back();
    // 	num_minus--;
    // 	num_plus--;
    // }
    if (num_plus < 2) {
      ans *= minus[minus.size() - 2];
      ans *= minus.back();
      minus.pop_back();
      minus.pop_back();
      num_minus -= 2;
      continue;
    }
    if (num_minus < 2) {
      ans *= plus[plus.size() - 2];
      ans *= plus.back();
      plus.pop_back();
      plus.pop_back();
      num_plus -= 2;
      continue;
    }
    ll a = plus[plus.size() - 2] * plus.back();
    ll b = minus[minus.size() - 2] * minus.back();
    if (a > b) {
      ans *= plus[plus.size() - 2];
      ans *= plus.back();
      plus.pop_back();
      plus.pop_back();
      num_plus -= 2;
    } else {
      ans *= minus[minus.size() - 2];
      ans *= minus.back();
      minus.pop_back();
      minus.pop_back();
      num_minus -= 2;
    }
  }

  cout << ans.x << endl;
  return 0;
  ////////////////////////////

  // const int MAX = 1001001001;
  // int last_minus = MAX;
  // int last_plus = MAX;
  // int num_minus = 0;
  // for(int i=0; i<K; i++){
  // 	if(vec[i].second == -1){
  // 		num_minus++;
  // 		last_minus = i;
  // 	}
  // 	else last_plus = i;
  // }
  // if(num_minus % 2 == 0 || N==K){
  // 	//A[0]~A[K-1]をとった時点で　正になる
  // 	//あるいは　N==Kで　選ぶ余地がない場合
  // 	mint ans(1);
  // 	for(int i=0; i<K; i++) ans *= vec[i].first;
  // 	cout << ans.x << endl;
  // 	return 0;
  // }

  // //以下num_minusが奇数のときの処理
  // int minus = MAX;
  // int plus = MAX;
  // for(int i=K; i<N; i++){
  // 	if(vec[i].second == 1) plus = min(plus, i);
  // 	else minus = min(minus, i);
  // }
  // if(last_plus == MAX && plus == MAX){//入力に正の値がないなら...
  // 	//答えは必ず 負になるので，絶対値の小さい方からかけてく
  // 	mint ans(1);
  // 	for(int i=0; i<K; i++) ans *= vec[N-1-i].first * vec[N-1-i].second;
  // 	cout << ans.x << endl;
  // 	return 0;
  // }

  // if(plus == MAX){
  // 	//K以降にプラスがないなら，
  // 	//A[0]~A[K-1]の中で絶対値が一番小さい正の数を
  // 	//A[K]以降の負の数と入れ替える
  // 	//この分岐にいる時点でlast_plusにはMAX以外の数が必ず入っている
  // 	mint ans(1);
  // 	for(int i=0; i<K; i++){
  // 		if(i==last_plus) continue;
  // 		ans *= vec[i].first;
  // 	}
  // 	ans *= vec[minus].first;
  // 	cout << ans.x << endl;
  // 	return 0;
  // }
  // if(minus == MAX){
  // 	//K以降にマイナスがないなら，
  // 	//A[0]~A[K-1]の中で絶対値が一番小さい負の数を
  // 	//A[K]以降の正の数と入れ替える
  // 	//(N==Kの場合は処理済みなので，minusかplusのどっちかにはMAX以外の数字が入っている
  // 	//A[i]に負の数がないと，プラスにできるので，この分岐にいる時点でlast_minusには必ずMAX以外の値が入ってる
  // 	mint ans(1);
  // 	for(int i=0; i<K; i++){
  // 		if(i==last_minus) continue;
  // 		ans *= vec[i].first;
  // 	}
  // 	ans *= vec[plus].first;
  // 	cout << ans.x << endl;
  // 	return 0;

  // }
  // //以下 plusにも minusにも MAX以外の値が入っている場合
  // //以下　本来なら vec[plus] / vec[last_minus] をしたいが
  // //　vec[i] > vec[j] (i>j)　なので，　それをやると0になる
  // // そのため　逆数で扱う
  // ll a = vec[last_minus].first / vec[plus].first;
  // ll b = vec[last_plus].first / vec[minus].first;
  // bool is_a;
  // if(a < b) is_a = true;
  // else is_a = false;
  // mint ans(1);
  // if(is_a){
  // 	// last_minusを使わず　plusを使う
  // 	for(int i=0; i<K; i++){
  // 		if(i == last_minus) continue;
  // 		ans *= vec[i].first;
  // 	}
  // 	ans *= vec[plus].first;
  // 	cout << ans.x << endl;
  // 	return 0;
  // }
  // else{
  // 	// last_plusを使わず minusを使う
  // 	for(int i=0; i<K; i++){
  // 		if(i == last_plus) continue;
  // 		ans *= vec[i].first;
  // 	}
  // 	ans *= vec[minus].first;
  // 	cout << ans.x << endl;
  // 	return 0;
  // }
}


Error: 0

Fixed submission:

#include "bits/stdc++.h"
using namespace std;
typedef long long ll;

template <typename TYPE> void print_vec(const vector<TYPE> &v) {
  for (int i = 0; i < v.size(); i++) {
    cout << v[i] << " ";
  }
  cout << endl;
}

template <typename TYPE> void print_vec2(const vector<vector<TYPE>> &v) {
  cout << endl;
  cout << "       ";
  for (int i = 0; i < v[0].size(); i++)
    cout << i << "   ";
  cout << endl;
  for (int i = 0; i < v.size(); i++) {
    cout << "i=" << i << ":   ";
    for (int j = 0; j < v[i].size(); j++) {
      if (v[i][j] == 0)
        cout << "\\x1B[0m" << v[i][j] << "   ";
      else
        cout << "\\x1B[31m" << v[i][j]
             << "   "; // https://stackoverrun.com/ja/q/12618775
    }
    cout << "\\x1B[0m" << endl;
  }
}

// https://github.com/atcoder-live/library/blob/master/mint.cpp
//  auto mod int
//  https://youtu.be/L8grWxBlIZ4?t=9858
//  https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
//  https://youtu.be/8uowVvQ_-Mo?t=1329 : division
const int mod = 1000000007;
// const int mod = 998244353;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }

int main() {
  int N, K;
  cin >> N >> K;
  vector<ll> A(N);
  for (int i = 0; i < N; i++)
    cin >> A[i];

  typedef pair<ll, int> p;
  // second: -1ならA[i]がマイナス, 1ならA[i]0以上
  vector<p> vec;
  for (int i = 0; i < N; i++) {
    if (A[i] >= 0)
      vec.emplace_back(A[i], 1);
    else
      vec.emplace_back(-1 * A[i], -1);
  }

  sort(vec.rbegin(), vec.rend());

  const int MAX = 1001001001;
  int last_minus = MAX;
  int last_plus = MAX;
  int num_minus = 0;
  for (int i = 0; i < K; i++) {
    if (vec[i].second == -1) {
      num_minus++;
      last_minus = i;
    } else
      last_plus = i;
  }
  if (num_minus % 2 == 0 || N == K) {
    // A[0]~A[K-1]をとった時点で　正になる
    // あるいは　N==Kで　選ぶ余地がない場合
    mint ans(1);
    for (int i = 0; i < K; i++)
      ans *= vec[i].first;
    cout << ans.x << endl;
    return 0;
  }

  // 以下num_minusが奇数のときの処理
  int minus = MAX;
  int plus = MAX;
  for (int i = K; i < N; i++) {
    if (vec[i].second == 1)
      plus = min(plus, i);
    else
      minus = min(minus, i);
  }
  if (last_plus == MAX && plus == MAX) { // 入力に正の値がないなら...
    // 答えは必ず 負になるので，絶対値の小さい方からかけてく
    mint ans(1);
    for (int i = 0; i < K; i++)
      ans *= vec[N - 1 - i].first * vec[N - 1 - i].second;
    cout << ans.x << endl;
    return 0;
  }

  if (plus == MAX) {
    // K以降にプラスがないなら，
    // A[0]~A[K-1]の中で絶対値が一番小さい正の数を
    // A[K]以降の負の数と入れ替える
    // この分岐にいる時点でlast_plusにはMAX以外の数が必ず入っている
    mint ans(1);
    for (int i = 0; i < K; i++) {
      if (i == last_plus)
        continue;
      ans *= vec[i].first;
    }
    ans *= vec[minus].first;
    cout << ans.x << endl;
    return 0;
  }
  if (minus == MAX) {
    // K以降にマイナスがないなら，
    // A[0]~A[K-1]の中で絶対値が一番小さい負の数を
    // A[K]以降の正の数と入れ替える
    //(N==Kの場合は処理済みなので，minusかplusのどっちかにはMAX以外の数字が入っている
    // A[i]に負の数がないと，プラスにできるので，この分岐にいる時点でlast_minusには必ずMAX以外の値が入ってる
    mint ans(1);
    for (int i = 0; i < K; i++) {
      if (i == last_minus)
        continue;
      ans *= vec[i].first;
    }
    ans *= vec[plus].first;
    cout << ans.x << endl;
    return 0;
  }
  // 以下 plusにも minusにも MAX以外の値が入っている場合
  // 以下　本来なら vec[plus] / vec[last_minus] をしたいが
  // 　vec[i] > vec[j] (i>j)　なので，　それをやると0になる
  //  そのため　逆数で扱う
  ll a = vec[last_minus].first / vec[plus].first;
  ll b = vec[last_plus].first / vec[minus].first;
  bool is_a;
  if (a < b)
    is_a = true;
  else
    is_a = false;
  mint ans(1);
  if (is_a) {
    // last_minusを使わず　plusを使う
    for (int i = 0; i < K; i++) {
      if (i == last_minus)
        continue;
      ans *= vec[i].first;
    }
    ans *= vec[plus].first;
    cout << ans.x << endl;
    return 0;
  } else {
    // last_plusを使わず minusを使う
    for (int i = 0; i < K; i++) {
      if (i == last_plus)
        continue;
      ans *= vec[i].first;
    }
    ans *= vec[minus].first;
    cout << ans.x << endl;
    return 0;
  }
}