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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <deque>
#include <iostream>
#include <numeric>
#include <string>
#include <utility>
#include <vector>

using namespace std;

const int mod = 1e9 + 7;

bool can_plus(int n_plus, int n_minus, int k) {
  if (k % 2 == 1) {
    if (n_plus == 0) {
      return false;
    }
    k--;
    n_plus--;
  }

  return n_plus + (n_minus / 2 * 2) >= k;
}

int main() {
  int n, k;
  cin >> n >> k;

  int a;
  bool has0 = false;

  deque<int> num1, num2, num; // plus, minus, both

  for (int i = 0; i < n; i++) {
    cin >> a;
    num.emplace_back(abs(a));
    if (a > 0) {
      num1.emplace_back(a);
    } else if (a < 0) {
      num2.emplace_back(abs(a));
    } else {
      has0 = true;
    }
  }

  fprintf(stderr, "num1 %lu, num2 %lu, has0 %d, k %d\\n", num1.size(),
          num2.size(), has0 ? 1 : 0, k);

  long long ans = 1;
  if (can_plus(num1.size(), num2.size(), k)) {
    cerr << "plus" << endl;

    sort(num1.begin(), num1.end(), greater<int>());
    sort(num2.begin(), num2.end(), greater<int>());

    // 正にできる -> 絶対値の最大値
    if (k % 2 == 1) {
      ans = num1[0];
      num1.pop_front();
      k--;
    }
    while (k >= 2) {
      long long x1 = num1.size() < 2 ? -1 : 1LL * num1[0] * num1[1];
      long long x2 = num2.size() < 2 ? -1 : 1LL * num2[0] * num2[1];
      if (x1 >= x2) {
        ans *= num1[0];
        num1.pop_front();
        k--;
      } else {
        ans *= x2 % mod;
        num2.pop_front();
        num2.pop_front();
        k -= 2;
      }
      ans %= mod;
    }
    if (k > 0) {
      ans *= num1[0];
      ans %= mod;
      num1.pop_front();
      k--;
    }
  } else if (has0) {
    cerr << "zero" << endl;
    ans = 0;
  } else {
    // 負になる -> 絶対値の最小値
    cerr << "minus" << endl;
    sort(num.begin(), num.end());

    while (k > 0) {
      ans *= num.front();
      ans %= mod;
      num.pop_front();
      k--;
    }

    ans = mod - ans;
  }
  cout << ans << endl;
  return 0;
}


Error: 0
plus
         2,      1
         3,      1
         4,      1


Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <deque>
#include <iostream>
#include <map>
#include <numeric>
#include <string>
#include <utility>
#include <vector>

using namespace std;

const int mod = 1e9 + 7;

bool can_plus(int n_plus, int n_minus, int k) {
  if (k % 2 == 1) {
    if (n_plus == 0) {
      return false;
    }
    k--;
    n_plus--;
  }

  return n_plus + (n_minus / 2 * 2) >= k;
}

int main() {
  int n, k;
  cin >> n >> k;

  int a;
  bool has0 = false;

  deque<int> num1, num2, num; // plus, minus, both

  for (int i = 0; i < n; i++) {
    cin >> a;
    num.emplace_back(abs(a));
    if (a > 0) {
      num1.emplace_back(a);
    } else if (a < 0) {
      num2.emplace_back(abs(a));
    } else {
      has0 = true;
    }
  }

  map<int, int> tmp;
  long long ans = 1;
  if (can_plus(num1.size(), num2.size(), k)) {
    cerr << "plus" << endl;

    sort(num1.begin(), num1.end(), greater<int>());
    sort(num2.begin(), num2.end(), greater<int>());

    // 正にできる -> 絶対値の最大値
    if (k % 2 == 1) {
      tmp[num1[0]]++;
      ans = num1[0];
      num1.pop_front();
      k--;
    }

    while (k >= 2) {
      long long x1 = num1.size() < 2 ? -1 : 1LL * num1[0] * num1[1];
      long long x2 = num2.size() < 2 ? -1 : 1LL * num2[0] * num2[1];
      if (x1 >= x2) {
        tmp[num1[0]]++;
        ans *= num1[0];
        num1.pop_front();
        k--;
      } else {
        tmp[num2[0]]++;
        tmp[num2[1]]++;
        ans *= x2 % mod;
        num2.pop_front();
        num2.pop_front();
        tmp[num1.front()]++;
        k -= 2;
      }
      ans %= mod;
    }
    if (k > 0) {
      tmp[num1[0]]++;
      ans *= num1[0];
      ans %= mod;
      num1.pop_front();
      k--;
    }
  } else if (has0) {
    cerr << "zero" << endl;
    ans = 0;
  } else {
    // 負になる -> 絶対値の最小値
    cerr << "minus" << endl;
    sort(num.begin(), num.end());

    while (k > 0) {
      ans *= num.front();
      ans %= mod;
      num.pop_front();
      k--;
    }

    ans = mod - ans;
  }
  cout << ans << endl;

  for (auto p : tmp) {
    fprintf(stderr, "%10d, %6d\\n", p.first, p.second);
  }

  return 0;
}