Problem p02616 (C++) — buggy submission, verdict: Time Limit Exceeded

#define _GLIBCXX_DEBUG
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
#define rep0(TMS) for (int CNT = 0; CNT < (int)(TMS); CNT++)
#define rep(CNT, GOAL) for (int CNT = 0; CNT < (int)(GOAL); CNT++)
#define rep2(CNT, START, GOAL)                                                 \\
  for (int CNT = (int)(START); CNT < (int)(GOAL); CNT++)
#define rep3(CNT, START, GOAL)                                                 \\
  for (int CNT = (int)(START); CNT > (int)(GOAL); CNT--)
#define all(CONT) begin(CONT), end(CONT)
#define itrep(ITR, CONT) for (auto ITR = begin(CONT); ITR != end(CONT); ITR++)
#define itrep1(ITR, CONT)                                                      \\
  for (auto ITR = next(begin(CONT)); ITR != end(CONT); ITR++)
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
void prec(const int &DIG) {
  cerr << fixed << setprecision(DIG);
  cout << fixed << setprecision(DIG);
}
template <typename T> void CERR(const T &ELEM) { cerr << ELEM; }
template <typename T, typename... Ts>
void CERR(const T &FIRST, const Ts &...REST) {
  CERR(FIRST);
  cerr << ", ";
  CERR(REST...);
}
template <typename T1, typename T2> void CERR(const pair<T1, T2> &PAIR) {
  cerr << "(";
  CERR(PAIR.first);
  cerr << ", ";
  CERR(PAIR.second);
  cerr << ")";
}
template <typename T> void CERR(const vector<T> &VEC) {
  cerr << "{ ";
  itrep(ITR, VEC) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T> void CERR1(const vector<T> &VEC) {
  cerr << "{ ";
  itrep1(ITR, VEC) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T> void CERR(const set<T> &SET) {
  cerr << "{ ";
  itrep(ITR, SET) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T> void CERR(const multiset<T> &MULTISET) {
  cerr << "{ ";
  itrep(ITR, MULTISET) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T1, typename T2> void CERR(const map<T1, T2> &MAP) {
  cerr << "{ ";
  itrep(ITR, MAP) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
#define db(OBJ)                                                                \\
  cerr << #OBJ << ": ";                                                        \\
  CERR(OBJ);                                                                   \\
  cerr << ", "
#define dbl(OBJ)                                                               \\
  cerr << #OBJ << ": ";                                                        \\
  CERR(OBJ);                                                                   \\
  cerr << "\\n"
#define db1(OBJ)                                                               \\
  cerr << #OBJ << ": ";                                                        \\
  CERR1(OBJ);                                                                  \\
  cerr << "\\n"
#define dbs(...)                                                               \\
  cerr << "(" << #__VA_ARGS__ << "): (";                                       \\
  CERR(__VA_ARGS__);                                                           \\
  cerr << ")\\n"
#define dbvv(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep(CNT, VV.size()) {                                                        \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR(VV[CNT]);                                                             \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define db01(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep(CNT, VV.size()) {                                                        \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR1(VV[CNT]);                                                            \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define db10(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep2(CNT, 1, VV.size()) {                                                    \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR(VV[CNT]);                                                             \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define db11(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep2(CNT, 1, VV.size()) {                                                    \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR1(VV[CNT]);                                                            \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define YN(FLG) cout << (FLG ? "YES" : "NO") << "\\n"
#define Yn(FLG) cout << (FLG ? "Yes" : "No") << "\\n"
#define yn(FLG) cout << (FLG ? "yes" : "no") << "\\n"
// const ll INF = 1'000'000'000'000'000'007;
const int INF = 1'000'000'007;
const ll MOD = 1'000'000'007; // 998'244'353;

ll rem(ll x) {
  x %= MOD;
  if (x < 0)
    x += MOD;
  return x;
}
ll mpow(ll x, ll n) {
  ll res = 1;
  x = rem(x);
  while (n > 0) {
    if (n & 1)
      res = rem(res * x);
    x = rem(x * x);
    n >>= 1;
  }
  return res;
}
ll minv(ll x) {
  assert(x = rem(x));
  return mpow(rem(x), MOD - 2);
}

struct mint {
  ll val;
  ll mpow(ll x, ll n) {
    ll res = 1;
    x = rem(x);
    while (n > 0) {
      if (n & 1)
        res = rem(res * x);
      x = rem(x * x);
      n >>= 1;
    }
    return res;
  }
  ll minv(ll x) {
    assert(x = rem(x));
    return mpow(rem(x), MOD - 2);
  }
  mint() { val = 0; }
  mint(ll val_) { val = rem(val_); }
  mint(const mint &other) { val = other.val; }
  mint operator=(ll val_) {
    val = rem(val_);
    return *this;
  }
  mint operator=(const mint &other) {
    val = other.val;
    return *this;
  }
  mint operator+(ll y) { return mint(val + rem(y)); }
  mint operator+(const mint &other) { return operator+(other.val); }
  void operator+=(ll y) { val = rem(val + rem(y)); }
  void operator+=(const mint &other) { operator+=(other.val); }
  mint operator-() { return mint(-val); }
  mint operator-(ll y) { return mint(val - rem(y)); }
  mint operator-(const mint &other) { return operator-(other.val); }
  void operator-=(ll y) { val = rem(val - rem(y)); }
  void operator-=(const mint &other) { operator-=(other.val); }
  mint operator*(ll y) { return mint(val * rem(y)); }
  mint operator*(const mint &other) { return operator*(other.val); }
  void operator*=(ll y) { val = rem(val * rem(y)); }
  void operator*=(const mint &other) { operator*=(other.val); }
  mint mpow(ll n) { return mint(mpow(val, n)); }
  mint mpow(const mint &other) { return mpow(other.val); }
  mint minv() { return mint(minv(val)); }
  mint operator/(ll y) { return mint(val * minv(y)); }
  mint operator/(const mint &other) { return operator/(other.val); }
  void operator/=(ll y) { val = rem(val * minv(y)); }
  void operator/=(const mint &other) { operator/=(other.val); }
};

int N, K;
vl A;
int p = 0, n = 0, z = 0;
vl Pos, Neg;
vl Abs;

int main() {
  cin >> N >> K;
  A = vl(N);
  rep(i, N) cin >> A[i];
  rep(i, N) {
    if (A[i] > 0) {
      p++;
      Pos.push_back(A[i]);
      Abs.push_back(abs(A[i]));
    } else if (A[i] < 0) {
      n++;
      Neg.push_back(A[i]);
      Abs.push_back(abs(A[i]));
    } else if (A[i] == 0) {
      z++;
      Abs.push_back(abs(A[i]));
    }
  }
  // dbs(p, n, z); dbl(Pos); dbl(Neg); dbl(Abs);
  // (0)N=Kの場合，全部かけるしかない（コーナーの処理）
  if (N == K) {
    mint ans = 1;
    rep(i, N) ans *= A[i];
    cout << ans.val << endl;
    return 0;
  }
  // (1)積が-にならざるを得ないのはどのような場合か。
  // z>0なら積を0にできる。以下，z=0, p+n=Nとする。
  // -をKn個,+をKp個選ぶとする。Kn+Kp=K.
  // K<=pならKp=p,Kn=0とすればよい。+にできる。
  // K>pであれば，Kpとしてあり得る値が1通りであり，かつ，Kn=K-Kpが奇数なら積が必ず-になる。
  // 「Kpとしてあり得る値が1通り」なのは，p=0(n=K)か，p+n=N=Kのとき（？）
  // 前者は，Kp=0, Kn=K(これは結局N=Kの場合に含まれる。), 後者はKp=p, Kn=n。
  // 積が-にならざるを得ないときは，絶対値をできるだけ小さくすることを考える。
  // 絶対値の小さい方から数をK個かける。その-1倍のmod 1e9+7を取る。
  if (z == 0 and p == 0 and K % 2 == 1) {
    sort(all(Abs));
    mint ans = -1;
    rep(i, K) ans *= Abs[i];
    cout << ans.val << endl;
    return 0;
  }
  // (2)積が0にならざるを得ない場合は ※この場合を別個に考えるのはやや恣意的
  // p+n<Kの場合。
  if (p + n < K) {
    cout << 0 << endl;
    return 0;
  }
  // (3)積を+にできる場合
  // 以上のどちらでもない場合，絶対値をできるだけ大きくすることを考える。
  // -の数を絶対値の大きい方から2個ずつペアにして掛ける。
  vl Bis;
  sort(all(Neg));
  rep(i, n / 2) Bis.push_back(Neg[2 * i] * Neg[2 * i + 1]);
  // dbl(Bis);
  // +の数は，(a)Kが偶数であれば，絶対値の大きい方から2個ずつペアにして掛ける。
  sort(all(Pos), greater<ll>());
  if (K % 2 == 0) {
    rep(i, p / 2) Bis.push_back(Pos[2 * i] * Pos[2 * i + 1]);
    // dbl(Bis);
    sort(all(Bis), greater<ll>());
    // dbl(Bis);
    mint ans = 1;
    rep(i, K / 2) ans *= Bis[i];
    cout << ans.val << endl;
  } else {
    // (b)Kが奇数であれば，まず絶対値が最大のものを掛け，その後，絶対値の大きい方から2個ずつペアにして掛ける。
    // ★ここでREが生じていた。Kが奇数でも+の数が1つもない場合がある。その場合の答えは0になる。
    // -,0,+でなく-と非負に分ければよかった。
    if (p == 0) {
      cout << 0 << endl;
      return 0;
    }
    rep(i, (p - 1) / 2) Bis.push_back(Pos[2 * i + 1] * Pos[2 * i + 2]);
    // dbl(Bis);
    sort(all(Bis), greater<ll>());
    // dbl(Bis);
    mint ans = Pos[0];
    rep(i, (K - 1) / 2) ans *= Bis[i];
    cout << ans.val << endl;
  }
}

Error: TLE

Fixed submission:

#define _GLIBCXX_DEBUG
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
#define rep0(TMS) for (int CNT = 0; CNT < (int)(TMS); CNT++)
#define rep(CNT, GOAL) for (int CNT = 0; CNT < (int)(GOAL); CNT++)
#define rep2(CNT, START, GOAL)                                                 \\
  for (int CNT = (int)(START); CNT < (int)(GOAL); CNT++)
#define rep3(CNT, START, GOAL)                                                 \\
  for (int CNT = (int)(START); CNT > (int)(GOAL); CNT--)
#define all(CONT) begin(CONT), end(CONT)
#define itrep(ITR, CONT) for (auto ITR = begin(CONT); ITR != end(CONT); ITR++)
#define itrep1(ITR, CONT)                                                      \\
  for (auto ITR = next(begin(CONT)); ITR != end(CONT); ITR++)
template <typename T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
void prec(const int &DIG) {
  cerr << fixed << setprecision(DIG);
  cout << fixed << setprecision(DIG);
}
template <typename T> void CERR(const T &ELEM) { cerr << ELEM; }
template <typename T, typename... Ts>
void CERR(const T &FIRST, const Ts &...REST) {
  CERR(FIRST);
  cerr << ", ";
  CERR(REST...);
}
template <typename T1, typename T2> void CERR(const pair<T1, T2> &PAIR) {
  cerr << "(";
  CERR(PAIR.first);
  cerr << ", ";
  CERR(PAIR.second);
  cerr << ")";
}
template <typename T> void CERR(const vector<T> &VEC) {
  cerr << "{ ";
  itrep(ITR, VEC) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T> void CERR1(const vector<T> &VEC) {
  cerr << "{ ";
  itrep1(ITR, VEC) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T> void CERR(const set<T> &SET) {
  cerr << "{ ";
  itrep(ITR, SET) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T> void CERR(const multiset<T> &MULTISET) {
  cerr << "{ ";
  itrep(ITR, MULTISET) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
template <typename T1, typename T2> void CERR(const map<T1, T2> &MAP) {
  cerr << "{ ";
  itrep(ITR, MAP) {
    CERR(*ITR);
    cerr << ", ";
  }
  cerr << "}";
}
#define db(OBJ)                                                                \\
  cerr << #OBJ << ": ";                                                        \\
  CERR(OBJ);                                                                   \\
  cerr << ", "
#define dbl(OBJ)                                                               \\
  cerr << #OBJ << ": ";                                                        \\
  CERR(OBJ);                                                                   \\
  cerr << "\\n"
#define db1(OBJ)                                                               \\
  cerr << #OBJ << ": ";                                                        \\
  CERR1(OBJ);                                                                  \\
  cerr << "\\n"
#define dbs(...)                                                               \\
  cerr << "(" << #__VA_ARGS__ << "): (";                                       \\
  CERR(__VA_ARGS__);                                                           \\
  cerr << ")\\n"
#define dbvv(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep(CNT, VV.size()) {                                                        \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR(VV[CNT]);                                                             \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define db01(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep(CNT, VV.size()) {                                                        \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR1(VV[CNT]);                                                            \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define db10(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep2(CNT, 1, VV.size()) {                                                    \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR(VV[CNT]);                                                             \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define db11(VV)                                                               \\
  cerr << #VV << ": {\\n";                                                      \\
  rep2(CNT, 1, VV.size()) {                                                    \\
    cerr << #VV << "[" << CNT << "]: ";                                        \\
    CERR1(VV[CNT]);                                                            \\
    cerr << ",\\n";                                                             \\
  }                                                                            \\
  cerr << "}\\n"
#define YN(FLG) cout << (FLG ? "YES" : "NO") << "\\n"
#define Yn(FLG) cout << (FLG ? "Yes" : "No") << "\\n"
#define yn(FLG) cout << (FLG ? "yes" : "no") << "\\n"
// const ll INF = 1'000'000'000'000'000'007;
const int INF = 1'000'000'007;
const ll MOD = 1'000'000'007; // 998'244'353;

ll rem(ll x) {
  x %= MOD;
  if (x < 0)
    x += MOD;
  return x;
}
ll mpow(ll x, ll n) {
  ll res = 1;
  x = rem(x);
  while (n > 0) {
    if (n & 1)
      res = rem(res * x);
    x = rem(x * x);
    n >>= 1;
  }
  return res;
}
ll minv(ll x) {
  assert(x = rem(x));
  return mpow(rem(x), MOD - 2);
}

struct mint {
  ll val;
  ll mpow(ll x, ll n) {
    ll res = 1;
    x = rem(x);
    while (n > 0) {
      if (n & 1)
        res = rem(res * x);
      x = rem(x * x);
      n >>= 1;
    }
    return res;
  }
  ll minv(ll x) {
    assert(x = rem(x));
    return mpow(rem(x), MOD - 2);
  }
  mint() { val = 0; }
  mint(ll val_) { val = rem(val_); }
  mint(const mint &other) { val = other.val; }
  mint operator=(ll val_) {
    val = rem(val_);
    return *this;
  }
  mint operator=(const mint &other) {
    val = other.val;
    return *this;
  }
  mint operator+(ll y) { return mint(val + rem(y)); }
  mint operator+(const mint &other) { return operator+(other.val); }
  void operator+=(ll y) { val = rem(val + rem(y)); }
  void operator+=(const mint &other) { operator+=(other.val); }
  mint operator-() { return mint(-val); }
  mint operator-(ll y) { return mint(val - rem(y)); }
  mint operator-(const mint &other) { return operator-(other.val); }
  void operator-=(ll y) { val = rem(val - rem(y)); }
  void operator-=(const mint &other) { operator-=(other.val); }
  mint operator*(ll y) { return mint(val * rem(y)); }
  mint operator*(const mint &other) { return operator*(other.val); }
  void operator*=(ll y) { val = rem(val * rem(y)); }
  void operator*=(const mint &other) { operator*=(other.val); }
  mint mpow(ll n) { return mint(mpow(val, n)); }
  mint mpow(const mint &other) { return mpow(other.val); }
  mint minv() { return mint(minv(val)); }
  mint operator/(ll y) { return mint(val * minv(y)); }
  mint operator/(const mint &other) { return operator/(other.val); }
  void operator/=(ll y) { val = rem(val * minv(y)); }
  void operator/=(const mint &other) { operator/=(other.val); }
};

int N, K;
vl A;
int p = 0, n = 0, z = 0;
vl Pos, Neg;
vl Abs;

int main() {
  cin >> N >> K;
  A = vl(N);
  rep(i, N) cin >> A[i];
  rep(i, N) {
    if (A[i] > 0) {
      p++;
      Pos.push_back(A[i]);
      Abs.push_back(abs(A[i]));
    } else if (A[i] < 0) {
      n++;
      Neg.push_back(A[i]);
      Abs.push_back(abs(A[i]));
    } else if (A[i] == 0) {
      z++;
      Abs.push_back(abs(A[i]));
    }
  }
  dbs(p, n, z);
  dbl(Pos);
  dbl(Neg);
  dbl(Abs);
  // (0)N=Kの場合，全部かけるしかない（コーナーの処理）
  if (N == K) {
    mint ans = 1;
    rep(i, N) ans *= A[i];
    cout << ans.val << endl;
    return 0;
  }
  // (1)積が-にならざるを得ないのはどのような場合か。
  // z>0なら積を0にできる。以下，z=0, p+n=Nとする。
  // -をKn個,+をKp個選ぶとする。Kn+Kp=K.
  // K<=pならKp=p,Kn=0とすればよい。+にできる。
  // K>pであれば，Kpとしてあり得る値が1通りであり，かつ，Kn=K-Kpが奇数なら積が必ず-になる。
  // 「Kpとしてあり得る値が1通り」なのは，p=0(n=K)か，p+n=N=Kのとき（？）
  // 前者は，Kp=0, Kn=K(これは結局N=Kの場合に含まれる。), 後者はKp=p, Kn=n。
  // 積が-にならざるを得ないときは，絶対値をできるだけ小さくすることを考える。
  // 絶対値の小さい方から数をK個かける。その-1倍のmod 1e9+7を取る。
  if (z == 0 and p == 0 and K % 2 == 1) {
    sort(all(Abs));
    mint ans = -1;
    rep(i, K) ans *= Abs[i];
    cout << ans.val << endl;
    return 0;
  }
  // (2)積が0にならざるを得ない場合は ※この場合を別個に考えるのはやや恣意的
  // p+n<Kの場合。
  if (p + n < K) {
    cout << 0 << endl;
    return 0;
  }
  // (3)積を+にできる場合
  // 以上のどちらでもない場合，絶対値をできるだけ大きくすることを考える。
  // -の数を絶対値の大きい方から2個ずつペアにして掛ける。
  vl Bis;
  sort(all(Neg));
  rep(i, n / 2) Bis.push_back(Neg[2 * i] * Neg[2 * i + 1]);
  dbl(Bis);
  // +の数は，(a)Kが偶数であれば，絶対値の大きい方から2個ずつペアにして掛ける。
  sort(all(Pos), greater<ll>());
  if (K % 2 == 0) {
    rep(i, p / 2) Bis.push_back(Pos[2 * i] * Pos[2 * i + 1]);
    dbl(Bis);
    sort(all(Bis), greater<ll>());
    dbl(Bis);
    mint ans = 1;
    rep(i, K / 2) ans *= Bis[i];
    cout << ans.val << endl;
  } else {
    // (b)Kが奇数であれば，まず絶対値が最大のものを掛け，その後，絶対値の大きい方から2個ずつペアにして掛ける。
    // ★ここでREが生じていた。Kが奇数でも+の数が1つもない場合がある。その場合の答えは0になる。
    // -,0,+でなく-と非負に分ければよかった。
    if (p == 0) {
      cout << 0 << endl;
      return 0;
    }
    rep(i, (p - 1) / 2) Bis.push_back(Pos[2 * i + 1] * Pos[2 * i + 2]);
    dbl(Bis);
    sort(all(Bis), greater<ll>());
    dbl(Bis);
    mint ans = Pos[0];
    rep(i, (K - 1) / 2) ans *= Bis[i];
    cout << ans.val << endl;
  }
}