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

#include <algorithm>
#include <iostream>

using namespace std;
typedef long long ll;

int n, k;
ll arr[1000000];
int pos, neg, zero;
ll ans = 1L;
const ll mod = 1e9 + 7;

void cal() {
  ans = 1L;
  for (int i = 0; i < k; i++) {
    ans = (ans * arr[i]) % mod;
  }
}

int main() {
  cin >> n >> k;
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
    if (arr[i] > 0)
      pos++;
    else if (arr[i] == 0)
      zero++;
    else
      neg++;
  }
  // 全选
  if (k == n) {
    for (int i = 0; i < n; i++)
      ans = (ans * (arr[i] % mod)) % mod;
    cout << (ans + mod) % mod;
    return 0;
  }
  // 选择奇数个并且所有数字都是负数
  if (k % 2 == 1 && neg == n) {
    sort(arr, arr + n, greater<ll>());
    for (int i = 0; i < k; i++)
      ans = (ans * (arr[i] % mod)) % mod;
    cout << (ans + mod) % mod;
    return 0;
  }

  // 剩余情况处理
  // 首先将所有数据按照绝对值排序，降序
  sort(arr, arr + n, [](const ll &a, const ll &b) { return abs(a) > abs(b); });
  // 选取前k个数字
  cal();
  // 答案为正，正确
  if (ans >= 0) {
    cout << ans % mod;
    return 0;
  } else {
    // 答案为负数，两种选择
    // 1.去掉最小的正数，换成没有选择的绝对值最大的负数
    ll minpos = k - 1, maxneg = k;
    while (minpos >= 0 && arr[minpos] < 0)
      minpos--; // 最小的正数
    while (maxneg < n && arr[maxneg] >= 0)
      maxneg++; // 最大负数
    // 2.去掉绝对值最小的负数，换成没有选择的最大非负数
    ll maxpos = k, minneg = k - 1;
    while (minneg >= 0 && arr[minneg] > 0)
      minneg--;
    while (maxpos < n && arr[maxpos] < 0)
      maxpos++;
    // 比较两者大小
    // 要考虑没有找到对应值的情况
    // minpos存在，前k项有正有负
    if (minpos != -1) {
      // maxneg不存在，即剩余部分均为正数
      // 测试用例
      // 5 2
      // 5 -4 3 2 1
      // ans 15
      if (maxneg == n) {
        // ans =((ans+2*mod) / arr[minneg] * arr[maxpos]) % mod;
        swap(arr[minneg], arr[maxpos]);
        cal();
      } else {
        // maxneg存在
        // maxpos不存在，剩余部分均为负数
        // 5 2
        // 5 -4 -3 -2 -1
        // 12
        if (maxpos == n) {
          // ans =((ans+2*mod) / arr[minpos] * arr[maxneg]) % mod;
          swap(arr[minpos], arr[maxneg]);
          cal();
        } else {
          // maxpos存在，剩余部分有正有负
          // 5 2
          // 5 -4 -3 2 1
          // 12
          if (arr[maxpos] * arr[minpos] < arr[minneg] * arr[maxneg]) {
            // ans =((ans+2*mod) / arr[minpos] * arr[maxneg]) % mod;
            swap(arr[minpos], arr[maxneg]);
            cal();
          } else {
            // ans =((ans+2*mod) / arr[minneg] * arr[maxpos]) % mod;
            swap(arr[minneg], arr[maxpos]);
            cal();
          }
        }
      }
    } else {
      // 前k项均为负数，剩余有正有负
      // 5 3
      //-5 -4 -3 2 -1
      // 40
      //  ans =((ans+2*mod) / arr[minneg] * arr[maxpos]) % mod;
      swap(arr[minneg], arr[maxpos]);
      cal();
    }
    cout << (ans + mod) % mod;
    return 0;
  }
}

Error: WA

Fixed submission:

#include <algorithm>
#include <iostream>

using namespace std;
typedef long long ll;

int n, k;
ll arr[1000000];
int pos, neg, zero;
ll ans = 1L;
const ll mod = 1e9 + 7;

int main() {
  cin >> n >> k;
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
    if (arr[i] > 0)
      pos++;
    else if (arr[i] == 0)
      zero++;
    else
      neg++;
  }
  // 全选
  if (k == n) {
    for (int i = 0; i < n; i++)
      ans = (ans * (arr[i] % mod)) % mod;
    cout << (ans + mod) % mod;
    return 0;
  }
  // 选择奇数个并且所有数字都是负数
  if (k % 2 == 1 && neg == n) {
    sort(arr, arr + n, greater<ll>());
    for (int i = 0; i < k; i++)
      ans = (ans * (arr[i] % mod)) % mod;
    cout << (ans + mod) % mod;
    return 0;
  }

  // 剩余情况处理
  // 首先将所有数据按照绝对值排序，降序
  sort(arr, arr + n, [](const ll &a, const ll &b) { return abs(a) > abs(b); });
  // 选取前k个数字
  for (int i = 0; i < k; i++) {
    ans = (ans * (arr[i] % mod)) % mod;
  }
  // 答案为正，正确
  if (ans >= 0) {
    cout << ans % mod;
    return 0;
  } else {
    // 答案为负数，两种选择
    // 1.去掉最小的正数，换成没有选择的绝对值最大的负数
    ll minpos = k - 1, maxneg = k;
    while (minpos >= 0 && arr[minpos] < 0)
      minpos--; // 最小的正数
    while (maxneg < n && arr[maxneg] >= 0)
      maxneg++; // 最大负数
    // 2.去掉绝对值最小的负数，换成没有选择的最大非负数
    ll maxpos = k, minneg = k - 1;
    while (minneg >= 0 && arr[minneg] > 0)
      minneg--;
    while (maxpos < n && arr[maxpos] < 0)
      maxpos++;
    // 比较两者大小
    // 要考虑没有找到对应值的情况
    // 两种情况一定有一种可以实现
    if (maxneg == n) {
      ans = ((ans / arr[minneg] + mod) * arr[maxpos] % mod) % mod;
    } else if (maxpos == n) {
      ans = ((ans / arr[minpos] + mod) * arr[maxneg] % mod) % mod;
    } else {
      if (arr[maxpos] * arr[minpos] < arr[minneg] * arr[maxneg]) {
        ans = ((ans / arr[minpos] + mod) * arr[maxneg] % mod) % mod;
      } else {
        ans = ((ans / arr[minneg] + mod) * arr[maxpos] % mod) % mod;
      }
    }

    cout << (ans + mod) % mod;
    return 0;
  }
}