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

#include <bits/stdc++.h>
using namespace std;

int main() {
  int64_t N, K;
  cin >> N >> K;
  vector<int64_t> A(N);
  for (int64_t &a : A) {
    cin >> a;
  }

  sort(A.begin(), A.end(), greater<int64_t>());

  constexpr int64_t MOD = 1e9 + 7;

  // 0以下の数字しかない場合は特別に処理
  if (A.front() == 0) {
    // 0がある場合はKが奇数なら0で逃げられる
    int64_t ans = 1;
    if (K % 2 == 0) {
      // 後ろからK個
      for (int64_t i = N - K; i < N; i++) {
        ans *= A[i];
        if (ans < 0) {
          ans += MOD * MOD;
        }
        ans %= MOD;
      }
    } else {
      ans = 0;
    }
    cout << ans << endl;
    return 0;
  } else if (A.front() < 0) {
    // 0が無い場合はKが奇数のとき前からK個取る
    int64_t ans = 1;
    if (K % 2 == 0) {
      // 後ろからK個
      for (int64_t i = N - K; i < N; i++) {
        ans *= A[i];
        if (ans < 0) {
          ans += MOD * MOD;
        }
        ans %= MOD;
      }
    } else {
      // 前からK個
      for (int64_t i = 0; i < K; i++) {
        ans *= A[i];
        if (ans < 0) {
          ans += MOD * MOD;
        }
        ans %= MOD;
      }
    }
    cout << ans << endl;
    return 0;
  }

  int64_t num_0 = count(A.begin(), A.end(), 0);

  // 数的に0を絶対選ばないといけない場合がある
  if (num_0 > N - K) {
    cout << 0 << endl;
    return 0;
  }

  // 0を除外する
  for (auto itr = A.begin(); itr != A.end();) {
    if (*itr == 0) {
      itr = A.erase(itr);
    } else {
      itr++;
    }
  }

  N = A.size();

  // 使わないN - K個をどこから選び始めるか
  int64_t best_index = K;
  int64_t minus_num =
      count_if(A.begin(), A.begin() + K, [](int64_t x) { return x < 0; });
  bool is_value_minus = (minus_num % 2 == 1);

  for (int64_t i = K - 2; i >= 0; i -= 2) {
    // iから使わないN - K個を選び始めたとき
    // 前回との違いは(A[i + N - K] + A[i + N - K + 1]) / (A[i] * A[i + 1])
    // これが1より大きければ増える、そうでなければ減る
    // 一度1より小さくなったらもう1より大きくなることはない
    int64_t signum = 1;
    signum *= (A[i + N - K] > 0 ? 1 : -1);
    signum *= (A[i + N - K + 1] > 0 ? 1 : -1);
    signum *= (A[i] > 0 ? 1 : -1);
    signum *= (A[i + 1] > 0 ? 1 : -1);
    if (is_value_minus && signum == -1) {
      best_index = i;
      is_value_minus = false;
      continue;
    }
    int64_t v = (A[i + N - K] * A[i + N - K + 1]) / (A[i] * A[i + 1]);
    if (v >= 1) {
      best_index = i;
    } else {
      break;
    }
  }

  int64_t ans = 1;
  bool has_odd_minus = false;
  for (int64_t i = 0; i < best_index; i++) {
    ans *= A[i];
    if (ans < 0) {
      ans += MOD * MOD;
    }
    ans %= MOD;

    if (A[i] < 0) {
      has_odd_minus = !has_odd_minus;
    }
  }
  for (int64_t i = best_index + N - K; i < N; i++) {
    ans *= A[i];
    if (ans < 0) {
      ans += MOD * MOD;
    }
    ans %= MOD;

    if (A[i] < 0) {
      has_odd_minus = !has_odd_minus;
    }
  }

  // 最善が負だった場合は0があれば0に逃げる
  if (has_odd_minus && num_0 > 0) {
    ans = 0;
  }

  cout << ans << endl;
}

Error: -6
dbdb6e7b-6f20-44ee-b3cc-2999cdbdead7.out: /home/alex/Documents/bug-detection/input/Project_CodeNet/data/p02616/C++/s980999958.cpp:68: int main(): Assertion `false' failed.


Fixed submission:

#include <bits/stdc++.h>
using namespace std;

int main() {
  int64_t N, K;
  cin >> N >> K;
  vector<int64_t> A(N);
  for (int64_t &a : A) {
    cin >> a;
  }

  sort(A.begin(), A.end(), greater<int64_t>());

  constexpr int64_t MOD = 1e9 + 7;

  // 0以下の数字しかない場合は特別に処理
  if (A.front() == 0) {
    // 0がある場合はKが奇数なら0で逃げられる
    int64_t ans = 1;
    if (K % 2 == 0) {
      // 後ろからK個
      for (int64_t i = N - K; i < N; i++) {
        ans *= A[i];
        if (ans < 0) {
          ans += MOD * MOD;
        }
        ans %= MOD;
      }
    } else {
      ans = 0;
    }
    cout << ans << endl;
    return 0;
  } else if (A.front() < 0) {
    // 0が無い場合はKが奇数のとき前からK個取る
    int64_t ans = 1;
    if (K % 2 == 0) {
      // 後ろからK個
      for (int64_t i = N - K; i < N; i++) {
        ans *= A[i];
        if (ans < 0) {
          ans += MOD * MOD;
        }
        ans %= MOD;
      }
    } else {
      // 前からK個
      for (int64_t i = 0; i < K; i++) {
        ans *= A[i];
        if (ans < 0) {
          ans += MOD * MOD;
        }
        ans %= MOD;
      }
    }
    cout << ans << endl;
    return 0;
  }

  int64_t num_0 = count(A.begin(), A.end(), 0);

  // 数的に0を絶対選ばないといけない場合がある
  if (num_0 > N - K) {
    cout << 0 << endl;
    return 0;
  }

  assert(false);

  // 0を除外する
  for (auto itr = A.begin(); itr != A.end();) {
    if (*itr == 0) {
      itr = A.erase(itr);
    } else {
      itr++;
    }
  }

  // 使わないN - K個をどこから選び始めるか
  int64_t best_index = K;
  int64_t minus_num =
      count_if(A.begin(), A.begin() + K, [](int64_t x) { return x < 0; });
  bool is_value_minus = (minus_num % 2 == 1);

  for (int64_t i = K - 2; i >= 0; i -= 2) {
    // iから使わないN - K個を選び始めたとき
    // 前回との違いは(A[i + N - K] + A[i + N - K + 1]) / (A[i] * A[i + 1])
    // これが1より大きければ増える、そうでなければ減る
    // 一度1より小さくなったらもう1より大きくなることはない
    if (A[i] == 0 || A[i + 1] == 0) {
      // 大きくなったと見なして良い
      best_index = i;
    } else if (A[i + N - K] == 0 || A[i + N - K + 1] == 0) {
      if (is_value_minus) {
        best_index = i;
        break;
      } else {
        break;
      }
    } else {
      int64_t signum = 1;
      signum *= (A[i + N - K] > 0 ? 1 : -1);
      signum *= (A[i + N - K + 1] > 0 ? 1 : -1);
      signum *= (A[i] > 0 ? 1 : -1);
      signum *= (A[i + 1] > 0 ? 1 : -1);
      if (is_value_minus && signum == -1) {
        best_index = i;
        is_value_minus = false;
        continue;
      }
      int64_t v = (A[i + N - K] * A[i + N - K + 1]) / (A[i] * A[i + 1]);
      if (v > 1) {
        best_index = i;
      } else {
        break;
      }
    }
  }

  int64_t ans = 1;
  bool has_odd_minus = false;
  for (int64_t i = 0; i < best_index; i++) {
    ans *= A[i];
    if (ans < 0) {
      ans += MOD * MOD;
    }
    ans %= MOD;

    if (A[i] < 0) {
      has_odd_minus = !has_odd_minus;
    }
  }
  for (int64_t i = best_index + N - K; i < N; i++) {
    ans *= A[i];
    if (ans < 0) {
      ans += MOD * MOD;
    }
    ans %= MOD;

    if (A[i] < 0) {
      has_odd_minus = !has_odd_minus;
    }
  }

  // 最善が負だった場合は0があれば0に逃げる
  if (has_odd_minus && num_0 > 0) {
    ans = 0;
  }

  cout << ans << endl;
}