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 Kotlin (1.3.71) (judge verdict: Runtime Error)

import kotlin.math.absoluteValue

private const val MOD = 1_000_000_007

fun main() {
    val (_, k) = nextIntList()
    val nums = nextLongList().groupBy { it >= 0 }.mapValues { (_, value) ->
        value.sortedByDescending { it.absoluteValue }
    }
    val positives = nums.getOrDefault(true, emptyList())
    val negatives = nums.getOrDefault(false, emptyList())
    var posIndex = 0
    var negIndex = 0
    val res = mutableListOf<Long>()
    if (positives.isEmpty() && k % 2 == 1) {
        res.addAll(negatives.sortedDescending().take(k))
    } else {
        while (res.size < k) {
            when {
                res.size == k - 1 -> {
                    res.add(positives[posIndex])
                    posIndex++
                }
                negIndex >= negatives.lastIndex -> {
                    res.add(positives[posIndex])
                    posIndex++
                }
                posIndex >= positives.lastIndex -> {
                    res.add(negatives[negIndex])
                    res.add(negatives[negIndex + 1])
                    negIndex += 2
                }
                positives[posIndex] * positives[posIndex + 1] > negatives[negIndex] * negatives[negIndex + 1] -> {
                    res.add(positives[posIndex])
                    posIndex++
                }
                else -> {
                    res.add(negatives[negIndex])
                    res.add(negatives[negIndex + 1])
                    negIndex += 2
                }
            }
        }
    }
    println(res.stream().map { it.plus(MOD).rem(MOD) }.reduce { acc, l -> acc.times(l).rem(MOD) }.get())
}

// # Utils
// ## Input
fun next() = readLine()!!
fun nextInt() = next().toInt()
fun nextLong() = next().toLong()
fun nextDouble() = next().toDouble()
fun nextList() = next().split(" ")
fun nextIntList() = next().split(" ").map(String::toInt)
fun nextLongList() = next().split(" ").map(String::toLong)
fun nextDoubleList() = next().split(" ").map(String::toDouble)

// ## Array
inline fun <reified T> sizedArray(size: Int, default: T) = Array(size) { default }

// ## mod^-1
//    [NOTE] CANNOT use this for 0, mod, 2mod, 3mod ...(return wrong value)
fun modinv(num: Long, mod: Long): Long {
    var a = num
    var b = mod
    var u = 1L
    var v = 0L
    while (b > 0) {
        val t = a.div(b)
        a -= t * b
        a = b.also { b = a } // swap a and b
        u -= t * v
        u = v.also { v = u } // swap u and v
    }
    u %= mod
    if (u < 0) u += mod
    return u
}