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

// C++(GCC 9.2.1)
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using P = pair<LL, LL>;
#define repex(i, a, b, c) for (int i = a; i < b; i += c)
#define repx(i, a, b) repex(i, a, b, 1)
#define rep(i, n) repx(i, 0, n)
#define repr(i, a, b) for (int i = a; i >= b; i--)
#define pb push_back
#define a first
#define b second
#define all(x) x.begin(), x.end()
const LL MOD = 1e9 + 7;

int main() {

  // 1. 入力情報.
  int N, K;
  scanf("%d %d", &N, &K);
  LL a;
  vector<P> A;
  rep(i, N) {
    scanf("%lld", &a);
    if (a < 0)
      A.pb({-a, -1});
    else
      A.pb({a, 1});
  }

  // 2. sort.
  sort(all(A));

  // 3. 左右に分割.
  // 左: N - K個.
  int mL = 0, mR = 0; // 左半分, 右半分の負整数.
  int lp = -1, lm = -1; // 左半分で, 一番右側に出現する正整数, 負整数.
  int rp = -1, rm = -1; // 右半分で, 一番左側に出現する正整数, 負整数.
  repr(i, N - 1 - K, 0) {
    if (A[i].b < 0) {
      mL++;
      if (lm == -1)
        lm = i;
    } else {
      if (lp == -1)
        lp = i;
    }
  }

  // 右: K個.
  repx(i, N - K, N) {
    if (A[i].b < 0) {
      mR++;
      if (rm == -1)
        rm = i;
    } else {
      if (rp == -1)
        rp = i;
    }
  }

  // 4. 選んだ要素の積としてありえる最大値は？
  // 4-1. mR が 偶数個 の 場合.
  LL ans = 1LL;
  if (mR % 2 == 0)
    repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;

  // 4-2. mR が 奇数個 の 場合.
  if (mR % 2 != 0) {
    if (lp >= 0) {
      if (lm >= 0) {
        if (rp >= 0) {
          // 左半分, 右半分 ともに 正整数, 負整数 が 混在している場合.
          // (lm, lp, rm ,rp) = (〇, 〇, 〇, 〇) の 場合.
          if (rm >= 0) {
            LL a1 = A[lm].a * A[rm].a;
            LL a2 = A[lp].a * A[rp].a;
            repr(i, N - 1, N - K) if (i != rp && i != rm) ans *= A[i].a,
                ans %= MOD;
            ans *= (max(a1, a2) % MOD); // テストケース hand_04 対策.
            ans %= MOD;
            // puts("oooo");
          }
          // 左半分 は 正整数, 負整数 が 混在しており, 右半分 は
          // 正整数のみの場合. (lm, lp, rm ,rp) = (〇, 〇, ×, 〇) の 場合.
          if (rm == -1) {
            repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;
            // puts("ooxo");
          }
        } else {
          // 左半分 は 正整数, 負整数 が 混在しており, 右半分 は 負整数のみ の
          // 場合. (lm, lp, rm ,rp) = (〇, 〇, 〇, ×) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rm) ans *= A[i].a, ans %= MOD;
            ans *= A[lp].a;
            ans %= MOD;
            // puts("ooox");
          }
          // 左半分 は 正整数, 負整数 が 混在しており, 右半分がない場合.
          // (lm, lp, rm ,rp) = (〇, 〇, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      } else {
        if (rp >= 0) {
          // 左半分は, 正整数のみ, 右半分 ともに 正整数, 負整数 が
          // 混在している場合. (lm, lp, rm, rp) = (×, 〇, 〇, 〇) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rm) ans *= A[i].a, ans %= MOD;
            ans *= A[lp].a;
            ans %= MOD;
            // puts("xooo");
          }
          // 左半分 も 右半分 のいずれも正整数のみの場合.
          // (lm, lp, rm, rp) = (×, 〇, ×, 〇) の 場合.
          if (rm == -1) {
            repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;
            // puts("xoxo");
          }
        } else {
          // 左半分は, 正整数のみ, 右半分は 負整数のみ の 場合.
          // (lm, lp, rm, rp) = (×, 〇, 〇, ×) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rm) ans *= A[i].a, ans %= MOD;
            ans *= A[lp].a;
            ans %= MOD;
            // puts("xoox");
          }
          // 左半分 は 正整数のみ, 右半分がない場合.
          // (lm, lp, rm, rp) = (×, 〇, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      }
    } else {
      if (lm >= 0) {
        if (rp >= 0) {
          // 左半分 は 負整数のみ, 右半分は 正整数, 負整数 が 混在している場合.
          // (lm, lp, rm ,rp) = (〇, ×, 〇, 〇) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rp) ans *= A[i].a, ans %= MOD;
            ans *= A[lm].a;
            ans %= MOD;
            // puts("oxoo");
          }
          // 左半分 は 負整数のみ, 右半分 は 正整数のみ の 場合.
          // (lm, lp, rm ,rp) = (〇, ×, ×, 〇) の 場合.
          if (rm == -1) {
            repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;
            // puts("oxxo");
          }
        } else {
          // 左半分 は 負整数のみ, 右半分 は 負整数のみ の 場合.
          // (lm, lp, rm ,rp) = (〇, ×, 〇, ×) の 場合.
          if (rm >= 0) {
            rep(i, K) ans *= A[i].a, ans %= MOD;
            ans = ans * (MOD - 1) % MOD; // -1倍.
                                         // puts("oxox");
          }
          // 左半分 は 負整数のみ, 右半分がない場合.
          // (lm, lp, rm ,rp) = (〇, ×, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      } else {
        if (rp >= 0) {
          // 左半分がなく, 右半分 は 正整数, 負整数 が 混在している場合.
          // (lm, lp, rm, rp) = (×, ×, 〇, 〇) の 場合.
          if (rm >= 0) {
            rep(i, K) ans *= A[i].a, ans %= MOD;
            ans = ans * (MOD - 1) % MOD; // -1倍.
                                         // puts("xxoo");
          }
          // 左半分がなく, 右半分 は 正整数のみ の 場合.
          // (lm, lp, rm, rp) = (×, ×, ×, 〇) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        } else {
          // 左半分がなく, 右半分は 負整数のみ の 場合.
          // (lm, lp, rm, rp) = (×, ×, 〇, ×) の 場合.
          // random_m02 で 到達するパターン.
          if (rm >= 0) {
            rep(i, K) ans *= A[i].a, ans %= MOD;
            ans = ans * (MOD - 1) % MOD; // -1倍.
                                         // puts("xxox");
          }
          // 左半分, 右半分 ともにない場合.
          // (lm, lp, rm, rp) = (×, ×, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      }
    }
  }

  // 5. 出力.
  printf("%lld\\n", ans);
  return 0;
}

Error: 0

Fixed submission:

// C++(GCC 9.2.1)
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using P = pair<LL, LL>;
#define repex(i, a, b, c) for (int i = a; i < b; i += c)
#define repx(i, a, b) repex(i, a, b, 1)
#define rep(i, n) repx(i, 0, n)
#define repr(i, a, b) for (int i = a; i >= b; i--)
#define pb push_back
#define a first
#define b second
#define all(x) x.begin(), x.end()
const LL MOD = 1e9 + 7;

int main() {

  // 1. 入力情報.
  int N, K;
  scanf("%d %d", &N, &K);
  LL a;
  vector<P> A;
  rep(i, N) {
    scanf("%lld", &a);
    if (a < 0)
      A.pb({-a, -1});
    else
      A.pb({a, 1});
  }

  // 2. sort.
  sort(all(A));

  // 3. 左右に分割.
  // 左: N - K個.
  int mL = 0, mR = 0; // 左半分, 右半分の負整数.
  int lp = -1, lm = -1; // 左半分で, 一番右側に出現する正整数, 負整数.
  int rp = -1, rm = -1; // 右半分で, 一番左側に出現する正整数, 負整数.
  repr(i, N - 1 - K, 0) {
    if (A[i].b < 0) {
      mL++;
      if (lm == -1)
        lm = i;
    } else {
      if (lp == -1)
        lp = i;
    }
  }

  // 右: K個.
  repx(i, N - K, N) {
    if (A[i].b < 0) {
      mR++;
      if (rm == -1)
        rm = i;
    } else {
      if (rp == -1)
        rp = i;
    }
  }

  // 4. 選んだ要素の積としてありえる最大値は？
  // 4-1. mR が 偶数個 の 場合.
  LL ans = 1LL;
  if (mR % 2 == 0)
    repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;

  // 4-2. mR が 奇数個 の 場合.
  if (mR % 2 != 0) {
    if (lp >= 0) {
      if (lm >= 0) {
        if (rp >= 0) {
          // 左半分, 右半分 ともに 正整数, 負整数 が 混在している場合.
          // (lm, lp, rm ,rp) = (〇, 〇, 〇, 〇) の 場合.
          if (rm >= 0) {
            LL a1 = A[lm].a * A[rm].a;
            LL a2 = A[lp].a * A[rp].a;
            repr(i, N - 1, N - K) if (i != rp && i != rm) ans *= A[i].a,
                ans %= MOD;
            ans *= (max(a1, a2) % MOD); // テストケース hand_04 対策.
            ans %= MOD;
            // puts("oooo");
          }
          // 左半分 は 正整数, 負整数 が 混在しており, 右半分 は
          // 正整数のみの場合. (lm, lp, rm ,rp) = (〇, 〇, ×, 〇) の 場合.
          if (rm == -1) {
            repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;
            // puts("ooxo");
          }
        } else {
          // 左半分 は 正整数, 負整数 が 混在しており, 右半分 は 負整数のみ の
          // 場合. (lm, lp, rm ,rp) = (〇, 〇, 〇, ×) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rm) ans *= A[i].a, ans %= MOD;
            ans *= A[lp].a;
            ans %= MOD;
            // puts("ooox");
          }
          // 左半分 は 正整数, 負整数 が 混在しており, 右半分がない場合.
          // (lm, lp, rm ,rp) = (〇, 〇, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      } else {
        if (rp >= 0) {
          // 左半分は, 正整数のみ, 右半分 ともに 正整数, 負整数 が
          // 混在している場合. (lm, lp, rm, rp) = (×, 〇, 〇, 〇) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rm) ans *= A[i].a, ans %= MOD;
            ans *= A[lp].a;
            ans %= MOD;
            // puts("xooo");
          }
          // 左半分 も 右半分 のいずれも正整数のみの場合.
          // (lm, lp, rm, rp) = (×, 〇, ×, 〇) の 場合.
          if (rm == -1) {
            repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;
            // puts("xoxo");
          }
        } else {
          // 左半分は, 正整数のみ, 右半分は 負整数のみ の 場合.
          // (lm, lp, rm, rp) = (×, 〇, 〇, ×) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rm) ans *= A[i].a, ans %= MOD;
            ans *= A[lp].a;
            ans %= MOD;
            // puts("xoox");
          }
          // 左半分 は 正整数のみ, 右半分がない場合.
          // (lm, lp, rm, rp) = (×, 〇, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      }
    } else {
      if (lm >= 0) {
        if (rp >= 0) {
          // 左半分 は 負整数のみ, 右半分は 正整数, 負整数 が 混在している場合.
          // (lm, lp, rm ,rp) = (〇, ×, 〇, 〇) の 場合.
          if (rm >= 0) {
            repr(i, N - 1, N - K) if (i != rp) ans *= A[i].a, ans %= MOD;
            ans *= A[lm].a;
            ans %= MOD;
            // puts("oxoo");
          }
          // 左半分 は 負整数のみ, 右半分 は 正整数のみ の 場合.
          // (lm, lp, rm ,rp) = (〇, ×, ×, 〇) の 場合.
          if (rm == -1) {
            repr(i, N - 1, N - K) ans *= A[i].a, ans %= MOD;
            // puts("oxxo");
          }
        } else {
          // 左半分 は 負整数のみ, 右半分 は 負整数のみ の 場合.
          // (lm, lp, rm ,rp) = (〇, ×, 〇, ×) の 場合.
          if (rm >= 0) {
            rep(i, K) ans *= A[i].a, ans %= MOD;
            ans = ans * (MOD - 1) % MOD; // -1倍.
                                         // puts("oxox");
          }
          // 左半分 は 負整数のみ, 右半分がない場合.
          // (lm, lp, rm ,rp) = (〇, ×, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      } else {
        if (rp >= 0) {
          // 左半分がなく, 右半分 は 正整数, 負整数 が 混在している場合.
          // (lm, lp, rm, rp) = (×, ×, 〇, 〇) の 場合.
          if (rm >= 0) {
            rep(i, K) ans *= A[i].a, ans %= MOD;
            ans = ans * (MOD - 1) % MOD; // -1倍.
                                         // puts("xxoo");
          }
          // 左半分がなく, 右半分 は 正整数のみ の 場合.
          // (lm, lp, rm, rp) = (×, ×, ×, 〇) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        } else {
          // 左半分がなく, 右半分は 負整数のみ の 場合.
          // (lm, lp, rm, rp) = (×, ×, 〇, ×) の 場合.
          // ここには到達しないはず.
          if (rm >= 0)
            assert(0);
          // 左半分, 右半分 ともにない場合.
          // (lm, lp, rm, rp) = (×, ×, ×, ×) の 場合.
          // ここには到達しないはず.
          if (rm == -1)
            assert(0);
        }
      }
    }
  }

  // 5. 出力.
  printf("%lld\\n", ans);
  return 0;
}