Problem p02616 (C++)

Buggy submission (status: Runtime Error):
// https://atcoder.jp/contests/abc173/tasks/abc173_e
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;

template <long long Modulus = 1000000007> struct MInt {
  long long x;
  static const long long mod = Modulus;

  MInt(long long a = 0) : x((a % mod + mod) % mod) {}

  // operator
  MInt &operator=(const MInt &a) {
    x = a.x;
    return *this;
  }
  MInt &operator=(const long long &a) {
    *this = MInt(a);
    return *this;
  }

  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;
    x = x % mod;
    return *this;
  }

  MInt operator+(const MInt &a) const {
    MInt res(*this);
    return res += a;
  }

  MInt operator-(const MInt &a) const {
    MInt res(*this);
    return res -= a;
  }

  MInt operator*(const MInt &a) const {
    MInt res(*this);
    return res *= a;
  }

  MInt pow(long long t) const {
    if (t == 0)
      return 1;
    MInt a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // only for prime mod
  MInt Inv() const { return pow(mod - 2); }
  // only for prime mod
  MInt &operator/=(const MInt &a) { return (*this) *= a.Inv(); }
  MInt operator/(const MInt &a) const {
    MInt res(*this);
    return res /= a;
  }
};

template <class TMInt = MInt<>> struct Comb {
  std::vector<TMInt> fact, invfact, inv;
  long long mod;
  Comb(int n) : fact(n + 1), invfact(n + 1), inv(n + 1) {
    fact[0] = fact[1] = 1;
    mod = fact[0].mod;
    invfact[0] = invfact[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < n; ++i) {
      fact[i] = fact[i - 1] * TMInt(i);
      long long invx = inv[mod % i].x * (mod - mod / i) % mod;
      inv[i] = TMInt(invx);
      invfact[i] = invfact[i - 1] * inv[i];
    }
  }

  TMInt operator()(int n, int k) {
    if (k < 0 || n < k)
      return 0;
    return fact[n] * invfact[k] * invfact[n - k];
  }

  TMInt Perm(int n, int k) {
    if (k < 0 || n < k)
      return 0;
    return fact[n] * invfact[n - k];
  }
};

using modint = MInt<>;
using combination = Comb<modint>;

int main() {
  int N, K;
  cin >> N >> K;
  int mnum = 0;
  vector<ll> A(N);
  for (int i = 0; i < N; ++i) {
    cin >> A[i];
    if (A[i] < 0) {
      ++mnum;
    }
  }
  modint ans(1);
  if (mnum == N && K % 2 == 1) {
    sort(A.begin(), A.end(), std::greater<ll>());
    for (int i = 0; i < K; ++i) {
      ans *= A[i];
    }
    cout << ans.x << endl;
    return 0;
  } else if (N == K) {
    for (int i = 0; i < K; ++i) {
      ans *= A[i];
    }
    cout << ans.x << endl;
    return 0;
  }
  sort(A.begin(), A.end(), [](ll a, ll b) { return abs(a) > abs(b); });
  // pid : 正整数で末尾に一番近い要素のインデックス
  // mid : 負の整数で末尾に一番近い要素のインデックス
  int pid = -1, mid = -1;
  int cnt = 0; // 負の整数をカウント
  for (int i = 0; i < K; ++i) {
    if (A[i] > 0)
      pid = i;
    else if (A[i] < 0)
      mid = i, ++cnt;
  }

  if (cnt % 2 == 0) {
    for (int i = 0; i < K; ++i)
      ans *= A[i];
    cout << ans.x << endl;
    return 0;
  } else {
    // k 番目以降で最初に現れる正の整数のインデックスと負の整数のインデックス
    int idxp = -1, idxm = -1;
    for (int i = K; i < N; ++i) {
      if (A[i] > 0) {
        idxp = i;
        break;
      }
    }
    for (int i = K; i < N; ++i) {
      if (A[i] < 0) {
        idxm = i;
        break;
      }
    }

    // (+, -)を入れ替える or (-, +) を入れ替える
    if ((pid > -1 && idxm > -1) && (mid > -1 && idxp > -1)) {
      ll diff = abs(A[idxp]) * abs(A[pid]) - abs(A[idxm]) * abs(A[mid]);
      if (diff >= 0) {
        swap(A[mid], A[idxp]);
      } else if (diff < 0) {
        swap(A[pid], A[idxm]);
      }
    } else if (pid > -1 && idxm > -1 && mid > -1 && idxp == -1) {
      swap(A[pid], A[idxm]);
    } else if (pid > -1 && idxm > -1 && mid == -1 && idxp > -1) {
      swap(A[pid], A[idxm]);
    } else if (pid > -1 && idxm > -1 && mid == -1 && idxp == -1) {
      swap(A[pid], A[idxm]);
    } else if (mid > -1 && idxp > -1 && pid > -1 && idxm == -1) {
      swap(A[mid], A[idxp]);
    } else if (mid > -1 && idxp > -1 && pid == -1 && idxm > -1) {
      swap(A[mid], A[idxp]);
    } else if (mid > -1 && idxp > -1 && pid == -1 && idxm == -1) {
      swap(A[mid], A[idxp]);
    } else if (mid > -1 && pid > -1 && idxp == -1 && idxm == -1) {
      cout << 0 << endl;
      return 0;
    } else if (mid > -1 && pid == -1 && idxp == -1 && idxm > -1) {
      swap(A[mid], A[idxp]);
      for (int i = K; i < N; ++i) {
        if (A[i] == 0) {
          cout << 0 << endl;
          return 0;
        }
      }
    }
    for (int i = 0; i < K; ++i) {
      ans *= A[i];
    }
    cout << ans.x << endl;
    return 0;
  }

  return 0;
}


Fixed submission:
// https://atcoder.jp/contests/abc173/tasks/abc173_e
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;

template <long long Modulus = 1000000007> struct MInt {
  long long x;
  static const long long mod = Modulus;

  MInt(long long a = 0) : x((a % mod + mod) % mod) {}

  // operator
  MInt &operator=(const MInt &a) {
    x = a.x;
    return *this;
  }
  MInt &operator=(const long long &a) {
    *this = MInt(a);
    return *this;
  }

  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;
    x = x % mod;
    return *this;
  }

  MInt operator+(const MInt &a) const {
    MInt res(*this);
    return res += a;
  }

  MInt operator-(const MInt &a) const {
    MInt res(*this);
    return res -= a;
  }

  MInt operator*(const MInt &a) const {
    MInt res(*this);
    return res *= a;
  }

  MInt pow(long long t) const {
    if (t == 0)
      return 1;
    MInt a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // only for prime mod
  MInt Inv() const { return pow(mod - 2); }
  // only for prime mod
  MInt &operator/=(const MInt &a) { return (*this) *= a.Inv(); }
  MInt operator/(const MInt &a) const {
    MInt res(*this);
    return res /= a;
  }
};

template <class TMInt = MInt<>> struct Comb {
  std::vector<TMInt> fact, invfact, inv;
  long long mod;
  Comb(int n) : fact(n + 1), invfact(n + 1), inv(n + 1) {
    fact[0] = fact[1] = 1;
    mod = fact[0].mod;
    invfact[0] = invfact[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < n; ++i) {
      fact[i] = fact[i - 1] * TMInt(i);
      long long invx = inv[mod % i].x * (mod - mod / i) % mod;
      inv[i] = TMInt(invx);
      invfact[i] = invfact[i - 1] * inv[i];
    }
  }

  TMInt operator()(int n, int k) {
    if (k < 0 || n < k)
      return 0;
    return fact[n] * invfact[k] * invfact[n - k];
  }

  TMInt Perm(int n, int k) {
    if (k < 0 || n < k)
      return 0;
    return fact[n] * invfact[n - k];
  }
};

using modint = MInt<>;
using combination = Comb<modint>;

int main() {
  int N, K;
  cin >> N >> K;
  int mnum = 0;
  vector<ll> A(N);
  for (int i = 0; i < N; ++i) {
    cin >> A[i];
    if (A[i] < 0) {
      ++mnum;
    }
  }
  modint ans(1);
  if (mnum == N && K % 2 == 1) {
    sort(A.begin(), A.end(), std::greater<ll>());
    for (int i = 0; i < K; ++i) {
      ans *= A[i];
    }
    cout << ans.x << endl;
    return 0;
  } else if (N == K) {
    for (int i = 0; i < K; ++i) {
      ans *= A[i];
    }
    cout << ans.x << endl;
    return 0;
  }
  sort(A.begin(), A.end(), [](ll a, ll b) { return abs(a) > abs(b); });
  // pid : 正整数で末尾に一番近い要素のインデックス
  // mid : 負の整数で末尾に一番近い要素のインデックス
  int pid = -1, mid = -1;
  int cnt = 0; // 負の整数をカウント
  for (int i = 0; i < K; ++i) {
    if (A[i] > 0)
      pid = i;
    else if (A[i] < 0)
      mid = i, ++cnt;
  }

  if (cnt % 2 == 0) {
    for (int i = 0; i < K; ++i)
      ans *= A[i];
    cout << ans.x << endl;
    return 0;
  } else {
    // k 番目以降で最初に現れる正の整数のインデックスと負の整数のインデックス
    int idxp = -1, idxm = -1;
    for (int i = K; i < N; ++i) {
      if (A[i] > 0) {
        idxp = i;
        break;
      }
    }
    for (int i = K; i < N; ++i) {
      if (A[i] < 0) {
        idxm = i;
        break;
      }
    }

    // (+, -)を入れ替える or (-, +) を入れ替える
    if ((pid > -1 && idxm > -1) && (mid > -1 && idxp > -1)) {
      ll diff = abs(A[idxp]) * abs(A[pid]) - abs(A[idxm]) * abs(A[mid]);
      if (diff >= 0) {
        swap(A[mid], A[idxp]);
      } else if (diff < 0) {
        swap(A[pid], A[idxm]);
      }
    } else if (pid > -1 && idxm > -1 && mid > -1 && idxp == -1) {
      swap(A[pid], A[idxm]);
    } else if (pid > -1 && idxm > -1 && mid == -1 && idxp > -1) {
      swap(A[pid], A[idxm]);
    } else if (pid > -1 && idxm > -1 && mid == -1 && idxp == -1) {
      swap(A[pid], A[idxm]);
    } else if (mid > -1 && idxp > -1 && pid > -1 && idxm == -1) {
      swap(A[mid], A[idxp]);
    } else if (mid > -1 && idxp > -1 && pid == -1 && idxm > -1) {
      swap(A[mid], A[idxp]);
    } else if (mid > -1 && idxp > -1 && pid == -1 && idxm == -1) {
      swap(A[mid], A[idxp]);
    } else if (mid > -1 && pid > -1 && idxp == -1 && idxm == -1) {
      cout << 0 << endl;
      return 0;
    } else if (mid > -1 && pid == -1 && idxp == -1 && idxm > -1) {
      swap(A[mid], A[idxm]);
      for (int i = K; i < N; ++i) {
        if (A[i] == 0) {
          cout << 0 << endl;
          return 0;
        }
      }
    }
    for (int i = 0; i < K; ++i) {
      ans *= A[i];
    }
    cout << ans.x << endl;
    return 0;
  }

  return 0;
}