Problem:
Score : 500 points

Problem Statement

Given are N integers A_1,\ldots,A_N.

We will choose exactly K of these elements. Find the maximum possible product of the chosen elements.

Then, print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Constraints

1 \leq K \leq N \leq 2\times 10^5

|A_i| \leq 10^9

Input

Input is given from Standard Input in the following format:

N K
A_1 \ldots A_N

Output

Print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Sample Input 1

4 2
1 2 -3 -4

Sample Output 1

12

The possible products of the two chosen elements are 2, -3, -4, -6, -8, and 12, so the maximum product is 12.

Sample Input 2

4 3
-1 -2 -3 -4

Sample Output 2

1000000001

The possible products of the three chosen elements are -24, -12, -8, and -6, so the maximum product is -6.

We print this value modulo (10^9+7), that is, 1000000001.

Sample Input 3

2 1
-1 1000000000

Sample Output 3

1000000000

The possible products of the one chosen element are -1 and 1000000000, so the maximum product is 1000000000.

Sample Input 4

10 10
1000000000 100000000 10000000 1000000 100000 10000 1000 100 10 1

Sample Output 4

999983200

Be sure to print the product modulo (10^9+7).

Solution in Rust (1.42.0) (judge verdict: Runtime Error)

use std::collections::HashSet;

fn main() {
    // k = 1 の場合、与えられた要素の最大値を選択する。
    // k = n の場合は自明。
    //
    // 要素が全て負、かつkが奇数の場合は積を正の値にすることができないので、
    // 絶対値の小さい方から順にk個の要素を選択してその積をとればよい。
    //
    // 上記以外の場合は積を必ず正の値にできる。
    //
    // 全ての要素を絶対値で昇順にソートする。このとき、絶対値が同じであれば
    // 正の数がより大きいとする。
    // 絶対値の大きい方からk個の値を選択する。その中に含まれている負の数の個数
    // をmとする。
    //
    // 1. mが偶数(0を含む)の場合
    //   選択した要素の積は正の値になり、それが最大値である。
    //
    // 2. mが奇数の場合
    //   選択されずに残った要素から、絶対値が最も大きい値pを1つ選択する。
    //   2-1. pの選択肢に正負が無い場合（pが1種類に定まる場合）
    //     選択済の要素のうち、下記のいずれか1つを選択し、pと入れ替える。
    //     ・pが負 → 正の数のうち絶対値が最も小さいもの
    //     ・pが正 → 負の数のうち絶対値が最も小さいもの
    //   2-2. pに正負の選択肢がある場合
    //     選択済の要素のうち、絶対値が最も小さいものqを選択し、それとは符号が
    //     逆のpと入れ替える。
    //     qの選択肢が複数ある場合は適当に1つを選択してよい。

    let input: Vec<i32> = read_vec();
    let k = input[1] as usize;

    let nums: Vec<i64> = read_vec();

    println!("{}", calc(k, &nums));
}

fn read<T: std::str::FromStr>() -> T {
    let mut buf = String::new();
    std::io::stdin().read_line(&mut buf).ok();
    buf.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|s| s.parse().ok().unwrap())
        .collect()
}

const DIV: i64 = 1_000_000_000 + 7;

fn calc(k: usize, nums: &[i64]) -> i64 {
    if k == 1 {
        return prod_mod(&[*nums.iter().max().unwrap()]);
    } else if k == nums.len() {
        return prod_mod(nums);
    }

    let mut sorted = Vec::from(nums);
    sorted.sort_by(|a, b| {
        let abs_a = a.abs();
        let abs_b = b.abs();

        if abs_a == abs_b {
            return a.cmp(b);
        }

        abs_a.cmp(&abs_b)
    });

    if sorted.iter().all(|&n| n < 0) && k % 2 == 1 {
        return prod_mod(&sorted[..k]);
    }

    sorted.reverse();

    let (selected, rest) = sorted.split_at_mut(k);

    if selected.iter().filter(|&&n| n < 0).count() % 2 == 0 {
        return prod_mod(&selected);
    }

    let mut max_nums: Vec<&i64> = rest
        .iter()
        .take_while(|&&n| n.abs() == rest[0].abs())
        .collect::<HashSet<&i64>>()
        .into_iter()
        .collect();
    max_nums.sort();
    if max_nums.len() == 1 {
        let p = max_nums[0];
        let pos = selected.iter().rev().position(|&n| n > 0).unwrap();
        selected[pos] = *p;
    } else {
        let pos = selected.len() - 1;
        let p = if selected[pos] < 0 {
            max_nums[0]
        } else {
            max_nums[1]
        };
        selected[pos] = *p;
    }

    prod_mod(selected)
}

fn prod_mod(nums: &[i64]) -> i64 {
    nums.iter().fold(1, |acc, cur| acc * (cur.abs() % DIV) % DIV)
}