Problem:
Score: 400 points

Problem Statement

We have N integers A_1, A_2, ..., A_N.

There are \frac{N(N-1)}{2} ways to choose two of them and form a pair. If we compute the product of each of those pairs and sort the results in ascending order, what will be the K-th number in that list?

Constraints

All values in input are integers.

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

1 \leq K \leq \frac{N(N-1)}{2}

-10^9 \leq A_i \leq 10^9\ (1 \leq i \leq N)

Input

Input is given from Standard Input in the following format:

N K
A_1 A_2 \dots A_N

Output

Print the answer.

Sample Input 1

4 3
3 3 -4 -2

Sample Output 1

-6

There are six ways to form a pair. The products of those pairs are 9, -12, -6, -12, -6, 8.

Sorting those numbers in ascending order, we have -12, -12, -6, -6, 8, 9. The third number in this list is -6.

Sample Input 2

10 40
5 4 3 2 -1 0 0 0 0 0

Sample Output 2

6

Sample Input 3

30 413
-170202098 -268409015 537203564 983211703 21608710 -443999067 -937727165 -97596546 -372334013 398994917 -972141167 798607104 -949068442 -959948616 37909651 0 886627544 -20098238 0 -948955241 0 -214720580 277222296 -18897162 834475626 0 -425610555 110117526 663621752 0

Sample Output 3

448283280358331064

Solution in Kotlin (1.0.0) (judge verdict: Accepted)

import java.util.*

fun main(args: Array<String>) {
    val (N, K) = readInputLine().split(" ").map { it.toLong() }
    val AArr = readInputLine().split(" ").map { it.toLong() }

    val minus = mutableListOf<Long>()
    val zero = mutableListOf<Long>()
    val plus = mutableListOf<Long>()

    for (A in AArr) {
        when {
            A == 0L -> zero.add(A)
            A < 0L -> minus.add(A)
            else -> plus.add(A)
        }
    }

    val minusNum = minus.size.toLong() * plus.size.toLong()
    val zeroNum = minus.size.toLong() * zero.size.toLong() + plus.size.toLong() * zero.size.toLong() + zero.size.toLong() * (zero.size.toLong() - 1L) / 2L

    when {
        K <= minusNum -> {
            var l = (-1e18).toLong() - 1L
            var r = -1L

            minus.sort()

            while (r - l > 1L) {
                val mid = (l + r) / 2L
                var cnt = 0L
                plus.forEach { cnt += (upperBound(minus, (mid - it + 1L) / it)).toLong() }

                if (cnt >= K) {
                    r = mid
                } else {
                    l = mid
                }
            }

            println(r)
            return
        }
        K <= zeroNum -> {
            println(0)
        }
        else -> {
            val K = K - minusNum - zeroNum
            val minus = minus.map { it * -1L }.toMutableList()

            minus.sort()
            plus.sort()

            var l = -1L
            var r = 1e18.toLong()

            while (r - l > 1L) {
                val mid = (l + r) / 2L

                var cnt = plus.foldIndexed(0L, {
                    index: Int, acc: Long, l: Long ->
                    val tmp = upperBound(plus, mid / l).toLong()
                    acc + tmp + if (index < tmp) -1L else 0L
                })

                cnt += minus.foldIndexed(0L, {
                    index: Int, acc: Long, l: Long ->
                    val tmp = upperBound(minus, mid / l).toLong()
                    acc + tmp + if (index < tmp) -1L else 0L
                })

                if (cnt / 2L >= K) {
                    r = mid
                } else {
                    l = mid
                }
            }

            println(r)
        }
    }
}

fun readInputLine(): String {
    return readLine()!!
}

fun <T: Comparable<T>> upperBound(list: List<T>, value: T): Int {
    return Collections.binarySearch(list, value, { x, y -> if (x > y) 1 else -1}).inv()
}