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-----
4 3
3 3 -4 -2

-----Sample Output-----
-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.

Difficulty: interview

Starter code:

Solutions:
import numpy as np
n,k = map(int,input().split())
a = np.array(list(map(int,input().split())))
a.sort()
posi = a[a>0]
zero = a[a==0]
nega = a[a<0]

def cnt(x):
    c = 0
    if x >= 0:
        c += len(zero)*n
    c += np.searchsorted(a, x // posi, side = 'right').sum()
    c += (n-np.searchsorted(a, (- x - 1) // (-nega), side = 'right')).sum()
    c -= np.count_nonzero(a * a <= x)
    return c // 2

l = - 10 ** 18
r = 10 ** 18
while l + 1 < r:
    m = (l + r) // 2
    if cnt(m) < k:
        l = m
    else:
        r = m
print(r)

import numpy as np


def main():
    N, K = [int(x) for x in input().split()]
    A = np.array(input().split(), np.int64)
    A = np.sort(A)
    minus = A[A<0]
    zero = A[A==0]
    plus = A[A>0]


    def f(x):
        """number of products <=x
        """
        res = 0
        if x >= 0:
            res += len(zero) * N
        # positive
        res += np.searchsorted(A, x // plus, side="right").sum()

        # negative
        res += (N - np.searchsorted(A, (-x-1) // (-minus), side="right")).sum()

        # remove dup
        res -= np.count_nonzero(A*A <= x)
        res //= 2

        return res

    l = -10**18
    r = 10**18

    while l+1 < r:
        mid = (l+r)//2
        if f(mid) >= K:
            r = mid
        else:
            l = mid
    print(r)


def __starting_point():
    main()
__starting_point()

import numpy as np
n, k = map(int,input().split())
a = np.array(list(map(int,input().split())))
a.sort()
posi = a[a>0]
zero = a[a==0]
nega = a[a<0]
l = -10**18-1
r = 10**18+1
while r-l > 1:
    mid = (r+l)//2
    cnt = 0
    if mid >= 0:
        cnt += len(zero)*n
    cnt += a.searchsorted(mid//posi, side="right").sum()
    cnt += (n - a.searchsorted(-(-mid//nega), side="left")).sum()
    cnt -= np.count_nonzero(a*a <= mid)
    cnt //= 2
    if cnt >= k:
        r = mid
    else:
        l = mid
print(r)

def d_pairs():
    # 参考: https://maspypy.com/atcoder-参加感想-2019-02-16abc-155
    import numpy as np
    N, K = [int(i) for i in input().split()]
    A = np.array([int(i) for i in input().split()], np.int64)

    A = np.sort(A)
    zero = A[A == 0]
    positive = A[A > 0]
    negative = A[A < 0]

    def f(c):
        """数列 A から 2 要素を選んで積を取ったとき、c 以下となるようなペアの選び方"""
        count_pair = 0

        # a (数列の要素) == 0 かつ c >= 0 なら、a * x <= c となる x は数列の任意の要素
        if c >= 0:
            count_pair += len(zero) * N
        # a > 0 の場合
        count_pair += np.searchsorted(A, c // positive, side='right').sum()
        # a < 0 の場合 (全体から引くようにすると、見通しがよい)
        count_pair += (N - np.searchsorted(A, (-c - 1) // (-negative), side='right')).sum()
        # 添字の順序に制約があることを反映する
        count_pair -= np.count_nonzero(A * A <= c)  # 「添字が同じ要素を 2 度選んだ場合」を引く
        return count_pair // 2

    # 数列から要素を 2 個選んで積を取ったとき、制約からあり得る値の範囲
    lower, upper = -10 ** 18, 10 ** 18
    while upper - lower > 1:
        x = (lower + upper) // 2
        if f(x) >= K:
            upper = x
        else:
            lower = x
    return upper

print(d_pairs())

#abc_155_d
import numpy as np
n,k = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
a = np.array(a)
a.sort()

plus = a[a>0]
zero = a[a==0]
minus= a[a<0]

left = -10**18
right = 10**18

while left+1 < right:
    mid = (left+right)//2
    cnt = 0
    
    if mid >=0:
        cnt += len(zero) * n
    
    cnt += a.searchsorted(mid//plus, side="right").sum()
    cnt += (n - a.searchsorted(-(-mid//minus), side="left")).sum()
    cnt -= np.count_nonzero(a*a <= mid)
    cnt /= 2
    
    if cnt >= k:
        right = mid
    if cnt < k:
        left=mid
        
print(right)

import numpy as np
import sys

input = sys.stdin.readline

n, k = [int(x) for x in input().split()]
A = np.array([int(a) for a in input().split()], dtype="int64")

A = np.sort(A)

A_pos = A[A > 0]
A_neg = A[A < 0]
A_zero = A[A == 0]

# 積がc以下となる組み合わせの数を求める
def n_comb_lt(c):
    n_comb = 0
    # A[i] > 0であるA[i]について
    target = c // A_pos  # target以下の値がA[i]の相方
    n_comb += np.searchsorted(A, target, side="right").sum()

    # A[i] == 0であるA[i]について
    n_comb += n * len(A_zero) if c >= 0 else 0

    # A[i] < 0であるA[i]について
    target = -(-c // A_neg)
    n_comb += (n - np.searchsorted(A, target, side="left")).sum()

    # 組み合わせのうち、A[i]*A[i]となっているものを引いて、2で割る
    n_comb -= A[A * A <= c].size
    n_comb //= 2

    return n_comb

ok = -10 ** 18 - 1
ng = 10 ** 18 + 1

# k番目の積は、積がm未満となる組み合わせがk個未満となる最大のm
# ←→積が(m-1)以下となる組み合わせがk個未満となる最大のm
while ng - ok > 1:
    mid = (ng + ok) // 2
    if n_comb_lt(mid - 1) < k:
        ok = mid
    else:
        ng = mid

print(ok)

# coding: utf-8
import sys
import numpy as np

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

# neg, zero, posに分けて、二分探索
N, K = lr()
A = np.array(lr()); A.sort()
neg = A[A<0]
zero = A[A==0]
pos = A[A>0]

def check(x):
    '''x以下の積がK個以上あるならTrueを返す'''
    cnt = 0  # 最後に２でわる
    if x >= 0:
        cnt += len(zero) * N
    cnt += (np.searchsorted(A, x//pos, side='right')).sum()
    cnt += (N - np.searchsorted(A, (-x-1)//(-neg), side='right')).sum()
    cnt -= np.count_nonzero(A*A <= x)
    assert cnt % 2 == 0
    return (cnt//2) >= K

ok = 10**20; ng = -10**20
while abs(ng-ok) > 1:
    mid = (ok+ng) // 2
    if check(mid):
        ok = mid
    else:
        ng = mid

print(ok)
# 30


# -*- coding: utf-8 -*-
#尺取り法

import numpy as np
n, k = map(int,input().split())
a = np.array(list(map(int,input().split())))
a.sort()
posi = a[a>0]
zero = a[a==0]
nega = a[a<0]
#print(posi)
# 2分探索, midより小さいものを数える
l = -10**18-1
r = 10**18+1
while r-l > 1:
    mid = (r+l)//2
    cnt = 0
    if mid >= 0:
        cnt += len(zero)*n

    # a.searchsorted(v, side="left"): a[i-1] < v <= a[i]であるvのindexを返す
    # a.searchsorted(v, side="right"): a[i-1] <= v < a[i]であるvのindexを返す

    cnt += a.searchsorted(mid//posi, side="right").sum()
    cnt += (n - a.searchsorted(-(-mid//nega), side="left")).sum()
    cnt -= np.count_nonzero(a*a <= mid)
    cnt //= 2
    #print("mid:", mid)
    #print("mid//posi:", mid//posi)
    #print("search:", a.searchsorted(mid//posi,side="right"))
    #print("-(-mid//nega):", -(-mid//nega))
    #print("search:", a.searchsorted(-(-mid//nega),side="left"))
    #print("nonzero_count:", np.count_nonzero(a*a<=mid))
    #print("count:", cnt)
    #print('-' * 20)
    if cnt >= k:
        r = mid
    else:
        l = mid
print(r)

import sys
sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))
import numpy as np
def resolve():
    N, K = lr()
    A = np.sort(np.array(lr(), np.int64))
    z = A[A == 0]
    p = A[A > 0]
    n = A[A < 0]
    
    def count_func(x):
        cnt = 0
        if x >= 0:
            cnt += len(z) * N
        cnt += np.searchsorted(A, x // p, side='right').sum()
        cnt += (N - np.searchsorted(A, -(-x // n), side='left')).sum()
        cnt -= np.count_nonzero(A * A <= x)
        assert cnt % 2 == 0
        return cnt // 2
    
    l = -10 ** 18
    r = 10 ** 18
    while l + 1 < r:
        x = (l + r) // 2
        if count_func(x) >= K:
            r = x
        else:
            l = x
    
    print(r)
resolve()

import numpy as np
import sys
input=sys.stdin.readline
n, k = list(map(int, input().split()))
a = np.array(list(map(int, input().split())))
pos = np.sort(a[a>0])
neg = np.sort(np.abs(a[a<0]))
zero = (a==0).sum()

INF = 2*(10**18)
l = -INF
r = INF
while(r-l>1):
    mid = (l+r)//2
    cnt = 0
    if mid >= 0:
        cnt = len(pos)*len(neg)  #(+) * (-)
        cnt += (len(pos)+len(neg)) * zero # 0 * (non-zero)
        cnt += (zero*(zero-1))//2 # 0 * 0
        x = np.searchsorted(pos, mid//pos, side='right').sum() #(+) * (+)
        x += np.searchsorted(neg, mid//neg, side='right').sum() #(-) * (-)
        x -= (pos*pos<=mid).sum()
        x -= (neg*neg<=mid).sum()
        cnt += x/2
    else:
        #積がmid以上になれば良い -> midよりも小さい
        cnt = (len(neg) - np.searchsorted(neg, abs(mid)//pos + (mid%pos!=0), side='left')).sum()
    #print(mid, cnt)
    #cnt := 積がmid以下になる物の数
    #k番目の数　-> それ以下のものがk個以上ある事が必要
    #cntがk個よりも少ない -> 条件を満たしていない
    #cntがそれ以上ならok
    if cnt < k:
        l = mid
    else:
        r = mid
print(r)


import numpy as np
n,k=map(int,input().split())
a=np.array(list(map(int,input().split())))
a.sort()
p=a[a>0]
z=a[a==0]
m=a[a<0]
l=-10**18
r=10**18
while r-l>1:
  mid=(r+l)//2
  cnt=0
  if mid>=0:
    cnt+=len(z)*n
  cnt+=a.searchsorted(mid//p,side='right').sum()
  cnt+=(n-a.searchsorted(-(-mid//m),side='left')).sum()
  cnt-=np.count_nonzero(a*a<=mid)
  cnt//=2
  if cnt>=k:
    r=mid
  else:
    l=mid
print(r)

import bisect
import numpy as npy
n,k = map(int,input().split())
a = list(map(int,input().split()))
a.sort()
n0,np,nn = 0,0,0
for i in a:
  if i>0:  np += 1
  elif i == 0:  n0 += 1
  else:  nn += 1
kp = (np**2-np+nn**2-nn)//2
k0 = n0*(n-n0)+(n0**2-n0)//2
kn = nn*np
if kn < k <= kn+k0:
  print(0)
  return
nls = []
pls = []
for i in range(n):
  if a[i] < 0:
    nls.append(a[i])
  elif a[i] > 0:
    pls.append(a[i])
ln = len(nls)
lp = len(pls)
nls = npy.array(nls,dtype=npy.int64)
pls = npy.array(pls,dtype=npy.int64)
if k <= kn:
  l = a[0]*a[-1]-1
  r = 0
  while l+1 < r:
    m = (l+r)//2
    mls = m//nls
    tmp = npy.searchsorted(pls,mls,side="right").sum()
    if tmp > kn-k:
      l = m
    else:
      r = m
  print(l)
else:
  nls = -nls
  nls = nls[::-1]
  k -= kn+k0
  l = 0
  r = max(a[0]**2,a[-1]**2)+1
  while l+1 < r:
    m = (l+r)//2
    tmp  = npy.searchsorted(nls,m//nls,side="right").sum()
    tmp += npy.searchsorted(pls,m//pls,side="right").sum()
    tmp -= npy.searchsorted(nls**2,m,side="left")
    tmp -= npy.searchsorted(pls**2,m,side="left")
    if tmp >= 2*k:
      r = m
    else:
      l = m
  print(r)

import sys
input = sys.stdin.readline
import numpy as np

def main():
    N, K = map(int,input().split())
    A = np.sort(np.array(list(map(int, input().split())), np.int64))
    z = A[A == 0]
    p = A[A > 0]
    n = A[A < 0]
    
    def count_func(x):
        cnt = 0
        if x >= 0:
            cnt += len(z) * N
        cnt += np.searchsorted(A, x // p, side='right').sum()
        cnt += (N - np.searchsorted(A, -(-x // n), side='left')).sum()
        cnt -= np.count_nonzero(A * A <= x)
        assert cnt % 2 == 0
        return cnt // 2
    
    l = -10 ** 18
    r = 10 ** 18
    while l + 1 < r:
        x = (l + r) // 2
        if count_func(x) >= K:
            r = x
        else:
            l = x
    
    print(r)
    
def __starting_point():
    main()
__starting_point()

import numpy as np
import sys

input = sys.stdin.readline

n, k = [int(x) for x in input().split()]
A = np.array([int(a) for a in input().split()], dtype="int64")

A = np.sort(A)

A_pos = A[A > 0]
A_neg = A[A < 0]
A_zero = A[A == 0]

# 積がc以下となる組み合わせの数を求める
def n_comb_lt(c):
    n_comb = 0
    # A[i] > 0であるA[i]について
    target = c // A_pos  # target以下の値がA[i]の相方
    n_comb += np.searchsorted(A, target, side="right").sum()

    # A[i] == 0であるA[i]について
    n_comb += n * len(A_zero) if c >= 0 else 0

    # A[i] < 0であるA[i]について
    target = -(-c // A_neg)
    n_comb += (n - np.searchsorted(A, target, side="left")).sum()

    # 組み合わせのうち、A[i]*A[i]となっているものを引いて、2で割る
    n_comb -= A[A * A <= c].size
    n_comb //= 2

    return n_comb

ok = -10 ** 18 - 1
ng = 10 ** 18 + 1

# k番目の積は、積がm未満となる組み合わせがk個未満となる最大のm
# ←→積が(m-1)以下となる組み合わせがk個未満となる最大のm
while ng - ok > 1:
    mid = (ng + ok) // 2
    if n_comb_lt(mid - 1) < k:
        ok = mid
    else:
        ng = mid

print(ok)



import numpy as np
def resolve():
    n, k = list(map(int, input().split()))
    a = np.array(input().split(), dtype=np.int64)
    a.sort()

    zero = np.count_nonzero(a == 0)
    positive = a[a > 0]
    negative = a[a < 0]

    def count(x):  # 積が x 以下のペアは何個あるか？
        ans = 0
        if x >= 0:  # 片側が 0 の場合
            ans += n * zero
        ans += np.searchsorted(a, x // positive, side="right").sum()  # 片側が正の場合
        ans += n * len(negative) - np.searchsorted(a, -(-x // negative), side="left").sum()  # 片側が負の場合 切り上げは -(-a//b)
        ans -= np.count_nonzero(a * a <= x)  # 同じもの2つは選べない
        return ans // 2

    ok = 10 ** 18
    ng = -ok - 1
    while ok - ng > 1:  # 二分探索
        cen = (ok + ng) // 2
        if count(cen) >= k:
            ok = cen
        else:
            ng = cen
    print(ok)

def __starting_point():
    resolve()

__starting_point()

def main():
    import numpy as np
    from bisect import bisect_left, bisect_right

    N, K = map(int, input().split())
    A = list(map(int, input().split()))

    A.sort()

    n = bisect_left(A, 0)
    p = bisect_right(A, 0)

    Negative = np.array(A[:n], dtype = np.int64)
    Positive = np.array(A[p:], dtype = np.int64)

    Number_Negative = len(Negative) * len(Positive)
    Number_Positive = len(Negative) * (len(Negative) - 1) // 2 + len(Positive) * (len(Positive) - 1) // 2
    Number_Zero = N * (N - 1) // 2 - Number_Negative - Number_Positive

    # print (Number_Negative)
    # print (Negative)
    # print (Number_Positive)
    # print (Positive)
    # print (Number_Zero)

    def Ncount(x): #x以下の数を数える(x < 0)
        tmp = 0
        for a in Negative:
            tmp += len(Positive) - bisect_left(Positive, (x + a + 1) // a)
        # print (x, tmp)
        return tmp

    def Ncount1(x):
        tmp = (len(Positive) - np.searchsorted(Positive, (-x - 1) // (-Negative), side = 'right')).sum() 
        return tmp 

    def Pcount(x): #x以下の数を数える(x > 0)
        tmp = 0
        for index, a in enumerate(Positive):
            tmp += bisect_right(Positive[index + 1:], x // a)
        for index, b in enumerate(Negative):
            tmp += len(Negative[index + 1:]) - bisect_left(Negative[index + 1:], (x + b + 1) // b)
            # print (bisect_right(Negative[index + 1:], x / b))
        # print (x, tmp)
        return tmp

    def Pcount1(x):
        tmp = 0
        tmp += np.searchsorted(Positive, x // Positive, side = 'right').sum()
        tmp += (len(Negative) - np.searchsorted(Negative, (-x - 1) // (-Negative), side = 'rigth')).sum()
        tmp -= np.count_nonzero(Positive * Positive <= x)
        tmp -= np.count_nonzero(Negative * Negative <= x)
        return tmp // 2

    if Number_Negative >= K:
        # ここに二分探索を書く
        l = -10 ** 18
        r = 0
        while r - l > 1:
            mid = (l + r) // 2
            if K <= Ncount1(mid):
                r = mid
            else:
                l = mid
        print (r)
        return
            

    elif Number_Negative < K <= Number_Negative + Number_Zero:
        print (0)
        return

    else:
        # ここに二分探索を書く
        l = 0
        r = 10 ** 18
        K -= (Number_Negative + Number_Zero)
        while r - l > 1:
            mid = (l + r) // 2
            if K <= Pcount1(mid):
                r = mid
            else:
                l = mid

        print (r)
        # return

    # print (Pcount(l) + Number_Negative + Number_Zero)
    # print (Pcount(r) + Number_Negative + Number_Zero)

def __starting_point():
    main()
__starting_point()

def d_pairs():
    # 参考: https://maspypy.com/atcoder-参加感想-2019-02-16abc-155
    import numpy as np
    N, K = [int(i) for i in input().split()]
    A = np.array([int(i) for i in input().split()], np.int64)

    A = np.sort(A)
    zero = A[A == 0]
    positive = A[A > 0]
    negative = A[A < 0]

    def f(c):
        """数列 A から 2 要素を選んで積を取ったとき、c 以下となるようなペアの選び方"""
        count_pair = 0

        # a (数列の要素) == 0 かつ c >= 0 なら、a * x <= c となる x は数列の任意の要素
        if c >= 0:
            count_pair += len(zero) * N
        # a > 0 の場合
        count_pair += np.searchsorted(A, c // positive, side='right').sum()
        # a < 0 の場合 (全体から引くようにすると、見通しがよい)
        count_pair += (N - np.searchsorted(A, (-c - 1) // (-negative), side='right')).sum()
        # 添字の順序に制約があることを反映する
        count_pair -= np.count_nonzero(A * A <= c)  # 「添字が同じ要素を 2 度選んだ場合」を引く
        return count_pair // 2

    # 数列から要素を 2 個選んで積を取ったとき、制約からあり得る値の範囲
    lower, upper = -10 ** 18, 10 ** 18
    while upper - lower > 1:
        x = (lower + upper) // 2
        if f(x) >= K:
            upper = x
        else:
            lower = x
    return upper

print(d_pairs())

import numpy as np
N, K = map(int, input().split())
L = np.array(list(map(int, input().split())))

L = np.sort(L)
pos = L[0<L]
neg = L[0>L]
zero = len(L[L==0])

def f(x):
  tmp = 0
  if x>=0:
    tmp += zero*N
  tmp += np.searchsorted(L, x//pos, side='right').sum()
  tmp += (N - np.searchsorted(L, -(-x//neg), side='left')).sum()
  tmp -= np.count_nonzero(L*L<=x)
  return tmp//2

l, r = -10**18, 10**18
while l<r-1:
  m = (l+r)//2
  count = f(m)
  if count >= K:
    r = m
  else:
    l = m

print(r)

import numpy as np
N, K = map(int, input().split())
A = np.array(list(map(int, input().split())))
A = np.sort(A)

G = A[A > 0]
Z = A[A == 0]
L = A[A < 0]

l, r = 10**18, -10**18

while l-r > 1:
  # 「積がm以下になるペアの数」を調べる。
  m = (l+r) // 2

  # A[A > 0]内から条件を満たすものの数?
  Pk = np.searchsorted(A, m//G, side="right").sum()

  # A[A < 0]内から条件を満たすものの数?
  Nk = (N - np.searchsorted(A, (-m-1)//(-L), side="right")).sum()

  # 同じ要素同士の積は重複しているため、条件を満たしていたら減らす
  duplicate = np.count_nonzero(A*A <= m)

  # A[0]内から条件を満たすものの数?
  Zk = 0
  if m >= 0:
    Zk += len(Z) * N

  # 条件を満たす要素の数を合わせる
  k = Pk + Nk + Zk - duplicate
  
  # 全要素が二重になっている。重複要素を削除
  k //= 2

  # 条件を満たす要素数kがK個以上ならmを低く、Kより少ないならmを高くする
  if k >= K:
    l = m
  else:
    r = m
#lとrが一致すればmが一意に定まる
print(l)

import itertools
import numpy as np

N, K = list(map(int, input().split(' ')))
A = list(map(int, input().split(' ')))
A = np.sort(A)

positive = A[A>0]
negative = A[A<0]
zero = A[A==0]

l = -10**18
r = 10**18

while l + 1 < r:
    x = (l+r) // 2 # 中央位置
    cnt = 0
    if x >= 0:
        cnt += N * len(zero)
    
    # x//pos : 中央値/posのそれぞれの値
    cnt += A.searchsorted(x//positive, side="right").sum()
    cnt += (N - A.searchsorted(-(-x//negative), side="left")).sum()
    cnt -= np.count_nonzero(A * A <= x)
    cnt //= 2
 
    if cnt >= K:
        r = x
    else:
        l = x
print(r) 


import bisect
import numpy as np

N,K = list(map(int,input().split()))
A = list(map(int,input().split()))

#N,K = 9,9
#A = [-3,-2,-2,-2,0,0,1,2,2]

def simple():
    B = sorted([A[i] * A[j] for i in range(N) for j in range(i+1,N)])
    return B[K-1]

def solve():
    A.sort()

    iplus = bisect.bisect_right(A,0)
    izeros = bisect.bisect_left(A,0)

    pluss = np.array(A[iplus:]).astype(np.int64)
    zeros = A[izeros:iplus]
    minuss = np.array(A[:izeros]).astype(np.int64)

    nplus = len(pluss)
    nzero = len(zeros)
    nminus = len(minuss)

    npminus = nplus * nminus
    npzeros = nzero * (nplus + nminus) + nzero * (nzero-1)//2

    if npminus < K <= npminus + npzeros:
        return 0
    elif K <= npminus:
        mn = A[-1] * A[0] - 1
        mx = 0
        while mx-mn > 1:
            mid = (mn+mx)//2
            xs = -(-mid//minuss)
            cnt = nplus * nminus
            cnt -= np.sum(np.searchsorted(pluss,xs,side="left"))
            if cnt >= K:
                mx = mid
            else:
                mn = mid
        return mx
    else:
        nK = K - npminus - npzeros
        pluss2 = (-minuss)[::-1]
        mn = -1
        mx = max(A[0]**2, A[-1]**2)
        pluss_p2 = pluss**2
        pluss2_p2 = pluss2**2
        while mx-mn > 1:
            mid = (mn+mx)//2
            cnt = 0
            xs = mid//pluss
            cnt += np.sum(np.searchsorted(pluss,xs,side='right'))
            cnt -= np.count_nonzero(pluss_p2 <= mid)
            xs2 = mid//pluss2
            cnt += np.sum(np.searchsorted(pluss2,xs2,side='right'))
            cnt -= np.count_nonzero(pluss2_p2 <= mid)
            cnt = cnt //2
            #print(mn,mid,mx,cnt)
            if nK <= cnt:
                mx = mid
            else:
                mn = mid
        return mx

print((solve()))
#for K in range(1,N*(N-1)//2+1):
#    print(solve(),simple())



import numpy as np

n,k = map(int,input().split())
a = np.array(list(map(int,input().split())))

a.sort()
pos = a[a>0]
zero = a[a==0]
neg = a[a<0]
negpos = (neg*(-1))[::-1]

lenn = len(neg)
lenz = len(zero)
lenp = len(pos)

nnres = lenn * lenp
nzres = int(lenz*(lenn+lenp)+lenz*(lenz-1)/2)
npres = int(lenn*(lenn-1)/2 + lenp*(lenp-1)/2)

if k<=nnres:
    def count_nnres(x):
        cnt = np.searchsorted(neg,x//pos,side='right').sum()
        return int(cnt)
    left = -10**18
    right = -1
    while left+1<right:
        mid = (left+right)//2
        nebefore = count_nnres(mid)
        if nebefore >= k:
            right = mid
        elif nebefore < k:
            left = mid
    print(right)
    
elif nnres<k<=nnres+nzres:
    print(0)
    
elif nnres+nzres<k:
    def count_npres(x):
        cnt = 0
        cnt += int(np.searchsorted(pos,x//pos,side='right').sum() - ((x//pos)>=pos).sum())//2
        cnt += int(np.searchsorted(negpos,x//negpos,side='right').sum() - ((x//negpos)>=negpos).sum())//2
        return cnt
    k -= nnres+nzres
    left = 1
    right = 10**18
    while left+1<right:
        mid = (left+right)//2
        nebefore = count_npres(mid)
        if nebefore >= k:
            right = mid
        elif nebefore < k:
            left = mid
    print(right)

import numpy as np
n, k = list(map(int, input().split()))
a = np.array(list(map(int, input().split())))

a.sort()

plus = a[a > 0]
minus = a[a < 0]
zero = a[a == 0]

#infだと割ってもinf
left = -10 ** 18
right = 10 ** 18

while left + 1 < right:
    x = (left + right) // 2
    cnt = 0
    if x >= 0:
        cnt += n * len(zero)
    cnt += a.searchsorted(x // plus, side="right").sum()
    cnt += (n - a.searchsorted(-(-x // minus), side="left")).sum()
    cnt -= np.count_nonzero(a * a <= x)
    cnt //= 2

    if cnt >= k:
        right = x
    else:
        left = x

print(right)


#https://maspypy.com/atcoder-%E5%8F%82%E5%8A%A0%E6%84%9F%E6%83%B3-2019-02-16abc-155
import numpy as np
N,K=map(int,input().split())
A=np.array(list(map(int,input().split())))
A.sort()
G=A[A>0]
Z=A[A==0]
L=A[A<0]

ok=10**18+1
ng=-10**18-1

#x以下がK個以上であるxの最小値

while ok-ng>1:
  mid = (ng+ok)//2
  #mid以下のペアの個数を数える
  
  #正のもののうち、mid以下のペアの個数を数える
  cg=np.searchsorted(A,mid//G,side="right").sum()
  
  #負のもののうちmid以下のペアの個数を数える
  cl=(N-np.searchsorted(A,(-mid-1)//(-L),side="right")).sum()
  
  #同じ数字同士の積がmid以下のものを数える
  d = np.count_nonzero(A*A <= mid)
  
  #0がmid以下なら、それもプラスするために必要
  z=0
  if mid>=0:
    z += len(Z)*N
  
  c=cg+cl+z-d
  
  #二重になっているので、割る
  c //=2
  
  #mid以下のペアの個数がK個以上のとき
  if c>=K:
    ok=mid
  else:
    ng=mid
    
print(ok)   

import numpy as np

def count_pair(x):
    cnt = 0
    cnt += (n-np.searchsorted(A, x//A_nega, side='right')).sum()
    if x > 0:
        cnt += len(A_zero)*n
    cnt += np.searchsorted(A, -(-x//A_posi), side='left').sum()
    cnt = (cnt-(A**2 < x).sum())//2
    return cnt

n, k = list(map(int, input().split()))
* A, = list(map(int, input().split()))
A = np.array(A)
A = np.sort(A)
A_posi = A[A > 0]
A_zero = A[A == 0]
A_nega = A[A < 0]
inf = 10**18+1
l, r = -inf, inf
while r - l > 1:
    c = (l + r) // 2
    if count_pair(c) < k:
        l = c
    else:
        r = c
print(l)


import numpy as np

n, k = list(map(int, input().split()))
a = list(map(int, input().split()))

a = np.array(a)
a.sort()

nega = a[a<0]
zero = a[a==0]
posi = a[a>0]

l = -10**18-1
r = 10**18+1
while r - l > 1:
   mid = (r+l)//2
   cnt = 0
   if mid >= 0:
      cnt += len(zero)*n
   cnt += a.searchsorted(mid//posi, side='right').sum()
   cnt += (n - a.searchsorted(-(-mid//nega), side='left')).sum()
   cnt -= np.count_nonzero(a*a <= mid)
   cnt //=2
   if cnt >= k:
      r = mid
   else:
      l= mid

print(r)



import numpy as np

n, k = map(int, input().split())
a = np.array(input().split(), np.int64)

a = np.sort(a)
zero = a[a == 0]
pos = a[a > 0]
neg = a[a < 0]

def f(x):
    """count the number of products , <= x"""
    cnt_tpl = 0
    # zero and ...
    if x >= 0:
        cnt_tpl += len(zero) * n
    # positive and ...
    cnt_tpl += np.searchsorted(a, x // pos, side='right').sum()
    # negative and ...
    cnt_tpl += (n - np.searchsorted(a, (-x - 1) // (-neg), side='right')).sum()
    # a^2
    cnt_tpl -= np.count_nonzero(a * a <= x)
    assert cnt_tpl % 2 == 0
    return cnt_tpl // 2

left = -10 ** 18
right = 10 ** 18
while left + 1 < right:
    x = (left + right) // 2
    if f(x) >= k:
        right = x
    else:
        left = x

print(right)

import numpy as np
n, k = list(map(int,input().split()))

# np.int64をつけないと、後でA**2を計算したときに桁あふれする
A = np.array(sorted(list(map(int,input().split()))), np.int64)
posA = A[A > 0] # 正の数のみの配列
negA = A[A < 0] # 負の数のみの配列
z = (A==0).sum() # 0の個数

left = -10**18
right = 10**18

while left+1 < right:
    num = (left+right)//2
    # ペア積の配列の中で、numより小さいものの数を数えていく。
    count = 0 # まずは0で初期化する。
    # もしnumが0以上であれば、積がゼロになるペア積の数を足しこむ
    if num >= 0:
        # この段階では値がゼロのものについて自分との積をあえてカウントする
        count += z*n 
    # 正の数に対して、かけてもnumを超えない最大の数字のリスト
    limit_pos = num // posA
    # limit_posの各数字を下回る数がAの中に何個あるかのリスト
    limit_idx = np.searchsorted(A, limit_pos, side='right')
    count += limit_idx.sum()

    # 負の数に対して、かけてもnumを超えない最大の数字のリスト
    limit_neg = -(-num // negA)
    # limit_negの各数字を下回る数がAの中に何個あるかのリスト
    limit_idx = n - np.searchsorted(A, limit_neg, side='left')
    count += limit_idx.sum()
    
    duplicate_cases = (A ** 2 <= num).sum()

    count -= duplicate_cases
    count //= 2

    if count >= k:
        right = num
    else:
        left = num

print(right)



import numpy as np


def partsolve(A, x, positive, zero, negative):
    """
    :param A:
    :param x:
    :return: Aの積のペアの中で、x以下となるペアの個数
    """
    count = 0
    if x >= 0:
        count = len(zero) * len(A)
    P = x // positive
    Pc = np.searchsorted(A, P, side='right')
    count += Pc.sum()

    N = (-x-1) // -negative
    Nc = np.searchsorted(A, N, side='right')
    Nc = len(A) - Nc
    count += Nc.sum()

    count -= np.count_nonzero(A * A <= x)
    return count // 2

def solve(N, K, As):
    A = np.array(sorted(As), np.int64)
    positive = A[A > 0]
    zero = A[A == 0]
    negative = A[A < 0]

    left = -10 ** 18
    right = 10 ** 18
    while right - left > 1:
        mid = left + (right - left) // 2
        c = partsolve(A, mid, positive, zero, negative)
        if c < K:
            left = mid
        else:
            right = mid
    return right


def __starting_point():
    N, K = tuple(map(int, input().split(" ")))
    As = list(map(int, input().split(" ")))
    print((solve(N, K, As)))


__starting_point()

import numpy as np
def f(nums, a):
  return 0  if nums.size<=1 else (np.searchsorted(nums, a//nums, side='right').sum()-np.searchsorted(nums, int(pow(a, 1/2)), side='right'))//2

N, K=map(int, input().split())
A=np.sort(list(map(int, input().split())))

p=np.sum(A>0)
q=np.sum(A<0)
Z=N-p-q
AP=A[-p:] if p>0 else np.array([])
AN=A[:q] if q>0 else np.array([])

b=(N-Z)*Z+Z*(Z-1)//2
a=p*q

if K<=a:
  x=AP[-1]*AN[0]-1
  y=AP[0]*AN[-1]
  while y-x>1:
    tmp=(y+x)//2
    counter=np.searchsorted(AN, tmp//AP, side='right').sum()
    if counter<K:
      x=tmp
    else:
      y=tmp
  print(y)
elif K<=a+b:
  print(0)
else:
  x=0
  y=10**18
  K=K-a-b
  if q<=1:
    while y-x>1:
      tmp=(y+x)//2
      if f(AP, tmp)<K:
        x=tmp
      else:
        y=tmp
    print(y)
    return
    
  AN=AN[::-1]
  AN=-AN
  
  if p<=1:
    while y-x>1:
      tmp=(y+x)//2
      counter=f(AN, tmp)
      if counter<K:
        x=tmp
      else:
        y=tmp
    print(y)
    return
    
  while y-x>1:
    tmp=(y+x)//2
    if f(AP, tmp)+f(AN, tmp)<K:
      x=tmp
    else:
      y=tmp
  print(y)

import numpy as np

def check(mid):
  cnt=0
  if mid>=0:
    cnt+=len(zero)*N
  cnt+=np.searchsorted(A, mid//pos, side="right").sum()
  cnt+=(N-np.searchsorted(A, (-mid-1)//(-neg), side="right")).sum()
  cnt-=np.count_nonzero(A*A<=mid)
  return cnt//2

N,K=map(int,input().split())
A=np.array(sorted(map(int,input().split())))

pos=A[A>0]
zero=A[A==0]
neg=A[A<0]

high=10**18
low=-10**18
while low+1<high:
  mid=(high+low)//2
  if check(mid)>=K:
    high=mid
  else:
    low=mid
print(high)

import numpy as np
def resolve():
    n, k = map(int, input().split())
    a = np.array(input().split(), dtype=np.int64)
    a.sort()
 
    zero = np.count_nonzero(a == 0)
    positive = a[a > 0]
    negative = a[a < 0]
 
    def count(x):  # 積が x 以下のペアは何個あるか？
        ans = 0
        if x >= 0:  # 片側が 0 の場合
            ans += n * zero
        ans += np.searchsorted(a, x // positive, side="right").sum()  # 片側が正の場合
        ans += n * len(negative) - np.searchsorted(a, -(-x // negative), side="left").sum()  # 片側が負の場合 切り上げは -(-a//b)
        ans -= np.count_nonzero(a * a <= x)  # 同じもの2つは選べない
        return ans // 2
 
    ok = 10 ** 18
    ng = -ok - 1
    while ok - ng > 1:  # 二分探索
        cen = (ok + ng) // 2
        if count(cen) >= k:
            ok = cen
        else:
            ng = cen
    print(ok)
 
def __starting_point():
    resolve()
__starting_point()

from sys import stdin
import numpy as np
def main():
    #入力
    readline=stdin.readline
    n,k=map(int,readline().split())
    a=np.array(readline().strip().split(),dtype="int64")
    
    a.sort()
    neg=a[a<0]
    neg_p=neg**2
    zero=a[a==0]
    pos=a[a>0]
    pos_p=pos**2
    l=-10**18-1
    r=10**18
    while l<r-1:
        x=(l+r)//2
        cnt=0
        if len(neg)>0:
            cnt+=(len(a)-np.searchsorted(a,(x+neg+1)//neg)).sum()
            cnt-=len(neg_p[neg_p<=x])
        if len(zero)>0:
            if x>=0:
                cnt+=(len(a)-1)*len(zero)
        if len(pos)>0:
            cnt+=np.searchsorted(a,x//pos,side="right").sum()
            cnt-=len(pos_p[pos_p<=x])

        cnt//=2
        if cnt>=k: r=x
        else: l=x

    print(r)

def __starting_point():
    main()
__starting_point()

import numpy as np

from bisect import bisect

DEBUG = False


N, K = list(map(int, input().split()))
A = list(map(int, input().split()))

A.sort()
A = np.array(A, dtype=np.int64)
neg = A[A < 0]
zero = A[A == 0]
pos = A[A > 0]

# Only keep the abs value of the negatives and flip so it's sorted
revAbsNeg = -neg[::-1]


def countDistinctPairsLessThan(arr, prod):
    # Given a sorted array find the number of distinct pairs that are < prod
    # O(N * log(N)) where N = len(arr)

    N = arr.shape[0]
    assert arr.shape == (N,)
    count3 = np.sum(
        np.minimum(np.arange(N), np.searchsorted(arr, (prod - 1) // arr, side="right"))
    )

    if DEBUG:
        count = 0
        for i, x in enumerate(arr):
            count += bisect(arr, (prod - 1) // x, 0, i)

        count2 = 0
        for i in range(len(arr)):
            for j in range(i + 1, len(arr)):
                if arr[i] * arr[j] < prod:
                    count2 += 1
        assert count == count2 == count3
    return count3


def countPairsLessThanOrEqual(arr1, arr2, prod):
    # Given two sorted arrays containing *positive* numbers only,
    # find the number of pairs between the two arrays that are <= prod
    # O(N * log(M)) where N = len(arr1), M = len(arr2)
    if len(arr1) > len(arr2):
        arr1, arr2 = arr2, arr1

    count3 = np.sum(np.searchsorted(arr2, prod // arr1, side="right"))

    if DEBUG:
        count = 0
        for x in arr1:
            count += bisect(arr2, prod // x)
        count2 = 0
        for x in arr1:
            for y in arr2:
                if x * y <= prod:
                    count2 += 1
        assert count == count2 == count3
    return count3


def getIndex(prod):
    # Count number of pairs strictly less than prod
    count = 0
    if prod < 0:
        # All negatives except for the negatives with abs value less than or equal -prod
        count += len(pos) * len(neg)
        count -= countPairsLessThanOrEqual(pos, revAbsNeg, -prod)
    elif prod >= 0:
        # All negatives
        count += len(pos) * len(neg)
        if prod > 0:
            # All zeroes
            count += len(zero) * len(neg)
            count += (len(zero) * (len(zero) - 1)) // 2
            count += len(zero) * len(pos)
            # Positives with positives
            count += countDistinctPairsLessThan(pos, prod)
            # Negatives with negatives
            count += countDistinctPairsLessThan(revAbsNeg, prod)

    if DEBUG:
        count2 = 0
        for i in range(N):
            for j in range(i + 1, N):
                if A[i] * A[j] < prod:
                    count2 += 1
        assert count == count2
    return count


def bisect_f(f, lo, hi):
    if DEBUG:
        assert f(lo) and not f(hi)
    while hi - lo > 1:
        mid = (lo + hi) // 2
        if f(mid):
            lo = mid
        else:
            hi = mid
        if DEBUG:
            assert f(lo) and not f(hi)
    if DEBUG:
        assert hi - lo == 1
        assert f(lo) and not f(hi)
    return lo


def solve(K):
    lo = -10 ** 18
    hi = 10 ** 18 + 1
    if DEBUG:
        assert getIndex(lo) <= K < getIndex(hi)
    prod = bisect_f(lambda prod: getIndex(prod) <= K, lo, hi)
    if DEBUG:
        assert getIndex(prod) <= K < getIndex(prod + 1)
    return prod


if DEBUG:
    for k in range((N * (N - 1)) // 2):
        print(("k", k, solve(k)))

print((solve(K - 1)))  # K is 1-indexed


import numpy as np
n, k = list(map(int,input().split()))
a = np.array(list(map(int,input().split())))
a.sort()
posi = a[a>0]
zero = a[a==0]
nega = a[a<0]

# 2分探索, midより小さいものを数える
l = -10**18-1
r = 10**18+1
while r-l > 1:
    mid = (r+l)//2
    cnt = 0
    if mid >= 0:
        cnt += len(zero)*n
    
    # a.searchsorted(v, side="left"): a[i-1] < v <= a[i]であるvのindexを返す  
    # a.searchsorted(v, side="right"): a[i-1] <= v < a[i]であるvのindexを返す  

    cnt += a.searchsorted(mid//posi, side="right").sum()
    cnt += (n - a.searchsorted(-(-mid//nega), side="left")).sum()
    cnt -= np.count_nonzero(a*a <= mid)
    cnt //= 2
    # print("mid:", mid)
    # print("mid//posi:", mid//posi)
    # print("search:", a.searchsorted(mid//posi,side="right"))
    # print("-(-mid//nega):", -(-mid//nega))
    # print("search:", a.searchsorted(-(-mid//nega),side="left"))
    # print("nonzero_count:", np.count_nonzero(a*a<=mid))
    # print("count:", cnt)
    # print('-' * 20)
    if cnt >= k:
        r = mid
    else:
        l = mid
print(r)


import sys
import numpy as np
INF = 10**18+5
input = sys.stdin.readline
sys.setrecursionlimit(10**6)


def main():
    n, k = list(map(int, input().split()))
    a = list(map(int, input().split()))
    a = np.sort(a)
    ap = a[a > 0]
    an = a[a < 0]
    zc = n * (n - ap.size - an.size)

    l = -INF
    r = INF
    while(l+1 < r):
        x = (l+r)//2

        total = (n-np.searchsorted(a, -(-x // an), side='left')).sum()
        if x >= 0:
            total += zc
        total += np.searchsorted(a, x // ap, side='right').sum()
        total -= a[a*a <= x].size
        total //= 2
        if total < k:
            l = x
        else:
            r = x

    print(r)


main()


N,K=list(map(int, input().split()))
A=list(map(int, input().split()))
A=sorted(A)
import numpy as np
A=np.array(A,dtype="int64")
Z=A[A==0]
H=A[A<0]
S=A[A>0]
l,r=-10**19,10**19
while r-l>1:
  mid=(r+l)//2
  cnt=0
  cnt+=A.searchsorted(mid//S,side="right").sum()
  cnt+=(N-A.searchsorted((-mid-1)//(-H),side="right")).sum()
  cnt-=np.count_nonzero(A*A<=mid)
  if mid>=0:
    cnt+=len(Z)*N 
  cnt//=2
  if cnt>=K:
    r=mid
  else:
    l=mid 
print(r)


import numpy as np
n,k=list(map(int,input().split()))
a = np.array(list(map(int,input().split())))
a.sort()

p = a[a>0]
m = a[a<0]
z = np.count_nonzero(a==0)

def count(x):
  cnt = 0
  if x>=0:
    cnt+=z*n
  cnt += a.searchsorted(x//p,side='right').sum()
  cnt += n*len(m) - a.searchsorted(-(-x//m),side='left').sum()
  cnt -= np.count_nonzero(a*a<=x)
  return cnt//2
l,r = -10**19,10**19
while r-l>1:
  mid = (l+r)//2
  cnt = count(mid)
  if cnt >= k:
    r = mid
  else:
    l = mid
print(r)


import numpy as np

N, K = list(map(int, input().split()))
A = np.sort(np.array(input().split(),np.int64))
z = A[A == 0]
p = A[A > 0]
n = A[A < 0]



def check(x):
    # x以下の数がK個以上ある時、Trueを返す
    count = 0 #最後に２で割る
    if x >= 0:
        count += len(z) * N
    count += (np.searchsorted(A, x//p, side='right')).sum()
    count += (N - np.searchsorted(A, (-x-1)//(-n), side='right')).sum()
    count -= np.count_nonzero(A * A <= x) #ペアなので自分自身は駄目
    assert count % 2 == 0
    count //= 2
    return count >= K

left = - 10 ** 19 # NG
right = 10 ** 19 # OK
while right > left + 1:
    mid = (left+right) // 2
    if check(mid):
        right = mid
    else:
        left = mid

print(right)


import numpy as np

n, k = list(map(int, input().split()))

A = np.array(input().split(), np.int64)

A.sort()

posA = A[A > 0]
negA = A[A < 0]
zeros = (A==0).sum()

left = -10**18
right = 10**18

while left+1 < right:
    num = (left+right)//2
    
    less_count = 0
    
    if num >= 0:
        less_count += zeros * n
    
    limit_pair_for_pos = num // posA
    limit_idxs = np.searchsorted(A, limit_pair_for_pos, side='right')
    less_count += limit_idxs.sum()

    limit_pair_for_neg = -(num // -negA)
    limit_idxs = n - np.searchsorted(A, limit_pair_for_neg, side='left')
    less_count += limit_idxs.sum()

    duplicate_cases = (A**2 <= num).sum()
    less_count -= duplicate_cases
    less_count //= 2
    
    if less_count >= k:
        right = num
    else:
        left = num

print(right)


import numpy as np

n,k = map(int,input().split())
a = list(map(int,input().split()))
a = np.array(a)
a.sort()
plus = a[a>0]
zero = np.count_nonzero(a==0)
minus = a[a<0]

low = -10**20
hi = 10**20

while hi-low > 1:
    # n*nのマスからave以下という条件を満たす個数をカウントするイメージ
    item = 0
    ave = (hi+low)//2

    # aveがプラスの時ゼロの分は条件を満たすため加算してやる
    if ave >= 0:
        item += zero*n

    # bisect結果*(serchしたいplus) <= ave　を変形
    # bisect結果 <= ave//(serchしたいplus)　になる
    item += a.searchsorted(ave//plus,side='right').sum()

    # マイナスの方も式変形のやり方は同じ
    # マイナスの方は結果がaveより大きいものを除外する
    item += n*len(minus)-a.searchsorted(-(-ave//minus),side='left').sum()

    # 最後に条件は満たしているものの、自分自身をかけているものを引いてやる
    item -= np.count_nonzero(a*a <= ave)
    
    # 二分探索部分組み合わせの際に(a,b),(b,a)の２通り足してるので割る
    if item//2 >= k:
        hi = ave
    else:
        low = ave

print(hi)

from math import floor,ceil,sqrt,factorial,log
from collections import Counter, deque
from functools import reduce
import numpy as np
def S(): return input()
def I(): return int(input())
def MS(): return map(str,input().split())
def MI(): return map(int,input().split())
def LS(): return list(MS())
def LI(): return list(MI())
def LLS(): return [list(map(str, l.split() )) for l in input()]
def LLI(): return [list(map(int, l.split() )) for l in input()]
def LLSN(n: int): return [LS() for _ in range(n)]
def LLIN(n: int): return [LI() for _ in range(n)]

n, k = MI()

a = np.array(sorted([int(i) for i in input().split()]))

pos = a[a > 0]
zero = a[a == 0]
neg = a[a < 0]

# 2分探索, mid より小さいものを数える
l = -10 ** 18 - 1
r = 10 ** 18 + 1
while r - l > 1:
    mid = (r + l) // 2
    cnt = 0
    if mid >= 0:
        cnt += len(zero) * n
 
    cnt += a.searchsorted(mid // pos, side="right").sum()
    cnt += (n - a.searchsorted(-(-mid // neg), side="left")).sum()
    cnt -= np.count_nonzero(a * a <= mid)
    cnt //= 2
    if cnt >= k:
        r = mid
    else:
        l = mid

print(r)

import numpy as np
def main():
    n, k = list(map(int, input().split()))
    a = list(map(int, input().split()))
    a.sort()
    cnt_neg, cnt_zro, cnt_pos = 0, 0, 0
    neg_a, zro_a, pos_a = [], [], []
    n_ap = neg_a.append
    z_ap = zro_a.append
    p_ap = pos_a.append
    for v in a:
        if v < 0:
            cnt_neg += 1
            n_ap(v)
        elif v == 0:
            cnt_zro += 1
            z_ap(v)
        else:
            cnt_pos += 1
            p_ap(v)
    num_neg_pair = cnt_neg * cnt_pos
    num_pos_pair = cnt_neg*(cnt_neg-1)//2 + cnt_pos*(cnt_pos-1)//2
    num_zro_pair = n*(n-1)//2 - num_neg_pair - num_pos_pair
    if k <= num_neg_pair:
        neg_a = np.array(neg_a)
        pos_a = np.array(pos_a)
        l = -1*10**18
        r = 0
        while l+1 < r:
            p = (l+r)//2
            cnt = np.searchsorted(pos_a, p//neg_a, side="riget").sum()
            result = n*cnt_neg - (cnt + (cnt_neg + cnt_zro)*cnt_neg)
            if result < k:
                l = p
            else:
                r = p
        print(l)
    elif k <= num_neg_pair + num_zro_pair:
        print("0")
    else:
        k -= num_neg_pair + num_zro_pair
        for i in range(len(neg_a)):
            neg_a[i] = -neg_a[i]
        neg_a = np.array(neg_a)
        neg_a = np.sort(neg_a)
        pos_a = np.array(pos_a)
        l = 1
        r = 10**18+1
        while l+1 < r:
            p = (l+r)//2
            cnt_1 = np.searchsorted(neg_a, (p+neg_a-1)//neg_a, side="left").sum()
            cnt_2 = np.searchsorted(pos_a, (p+pos_a-1)//pos_a, side="left").sum()
            cnt_1 -= np.count_nonzero(neg_a < (p+neg_a-1)//neg_a)
            cnt_2 -= np.count_nonzero(pos_a < (p+pos_a-1)//pos_a)
            result = (cnt_1 + cnt_2)//2
            if result < k:
                l = p
            else:
                r = p
        print(l)

def __starting_point():
    main()

__starting_point()

# coding: utf-8
import numpy as np


def solve(*args: str) -> str:
    n, k = list(map(int, args[0].split()))
    A = np.array(sorted(map(int, args[1].split())))
    N = A[A < 0]
    P = A[0 < A]

    count = 0
    left, right = -10**18, 10**18
    while left+1 < right:
        x = (left+right)//2
        count = 0

        if k <= len(N)*len(P):
            count += (len(P)-np.searchsorted(P, -(-x//N), side='left')).sum()

        elif (n*(n-1) - len(N)*(len(N)-1) - len(P)*(len(P)-1))//2 < k:
            for D in (-(N[::-1]), P):
                count += np.searchsorted(D, x//D, side='right').sum()
                count -= len(D[D*D <= x])
            count //= 2
            count += (n*(n-1) - len(N)*(len(N)-1) - len(P)*(len(P)-1))//2

        else:
            right = 0
            break

        if count < k:
            left = x
        else:
            right = x

    return str(right)


def __starting_point():
    print((solve(*(open(0).read().splitlines()))))

__starting_point()

import numpy as np
N,K=map(int,input().split())
A=list(map(int,input().split()))

A=np.array(A)

A_pos=np.sort(A[A>0])
A_neg=np.sort(A[A<0])
A_neg2=-A_neg[::-1]
n_pos=len(A_pos)
n_neg=len(A_neg)
n_zero=N-n_pos-n_neg

def position_in_neg(x):
    y=n_pos-np.searchsorted(A_pos,x//A_neg,side='right')
    return y.sum()

def position_in_pos(x):
    z=np.searchsorted(A_pos,-(-x//A_pos),side='left')
    w=np.searchsorted(A_neg2,-(-x//A_neg2),side='left')
    tmp=len(A_pos[A_pos**2<x])+len(A_neg2[A_neg2**2<x])
    return (z.sum()+w.sum()-tmp)//2

def position(x):
    if x<0:
        return position_in_neg(x)
    elif x==0:
        return n_pos*n_neg
    else:
        return position_in_pos(x)+n_pos*n_neg+(n_pos+n_neg)*n_zero+n_zero*(n_zero-1)//2

l=-pow(10,18)
r=pow(10,18)
while(r-l>1):
    mid=(l+r)//2
    if position(mid)<K:
        l=mid
    else:
        r=mid
print(l)

import numpy as np
n,k = list(map(int,input().split()))
a = list(map(int,input().split()))
a = np.array(a)
a.sort()
p = a[a>0]
z = a[a==0]
m = a[a<0]
low = -10**18
high = 10**18
while high-low>1:
    mid = (high + low) //2
    count = 0
    if mid >= 0:
        count += len(z)*n
    count += a.searchsorted(mid//p,side = "right").sum()
    count += (n-a.searchsorted(-(-mid//m),side = "left")).sum()
    count -= np.count_nonzero(a*a <= mid)
    count /= 2
    if count >= k:
        high = mid
    if count < k:
        low = mid
print(high)


# https://maspypy.com/atcoder-%E5%8F%82%E5%8A%A0%E6%84%9F%E6%83%B3-2019-02-16abc-155
import numpy as np

N, K = list(map(int, input().split()))
A = np.array(list(map(int, input().split())))
A.sort()
G = A[A > 0]
Z = A[A == 0]
L = A[A < 0]

ok = 10 ** 18 + 1
ng = -10 ** 18 - 1

# x以下がK個以上であるxの最小値

while ok - ng > 1:
    mid = (ng + ok) // 2
    # mid以下のペアの個数を数える

    # 正のもののうち、mid以下のペアの個数を数える
    cg = np.searchsorted(A, mid // G, side="right").sum()

    # 負のもののうちmid以下のペアの個数を数える
    cl = (N - np.searchsorted(A, (mid + 1) // L, side="right")).sum()

    # 同じ数字同士の積がmid以下のものを数える
    d = np.count_nonzero(A * A <= mid)

    # 0がmid以下なら、それもプラスするために必要
    z = 0
    if mid >= 0:
        z += len(Z) * N

    c = cg + cl + z - d

    # 二重になっているので、割る
    c //= 2

    # mid以下のペアの個数がK個以上のとき
    if c >= K:
        ok = mid
    else:
        ng = mid

print(ok)


import numpy as np


def partsolve(A, x, positive, zero, negative):
    """
    :param A:
    :param x:
    :return: Aの積のペアの中で、x以下となるペアの個数
    """
    count = 0
    if x >= 0:
        count = len(zero) * len(A)
    P = x // positive
    Pc = np.searchsorted(A, P, side='right')
    count += Pc.sum()

    N = (-x-1) // -negative
    Nc = np.searchsorted(A, N, side='right')
    Nc = len(A) - Nc
    count += Nc.sum()

    count -= np.count_nonzero(A * A <= x)
    return count // 2

def solve(N, K, As):
    A = np.array(sorted(As), np.int64)
    positive = A[A > 0]
    zero = A[A == 0]
    negative = A[A < 0]

    left = -10 ** 18
    right = 10 ** 18
    while right - left > 1:
        mid = left + (right - left) // 2
        c = partsolve(A, mid, positive, zero, negative)
        if c < K:
            left = mid
        else:
            right = mid
    return right


def __starting_point():
    N, K = tuple(map(int, input().split(" ")))
    As = list(map(int, input().split(" ")))
    print((solve(N, K, As)))


__starting_point()

# coding: utf-8
import numpy as np


def solve(*args: str) -> str:
    n, k = list(map(int, args[0].split()))
    A = np.array(sorted(map(int, args[1].split())))
    N = A[A < 0]
    P = A[0 < A]

    count = 0
    left, right = -10**18, 10**18
    while left+1 < right:
        x = (left+right)//2
        count = (n-np.searchsorted(A, -(-x//N), side='left')).sum()
        count += n * (A == 0).sum() if 0 <= x else 0
        count += np.searchsorted(A, x//P, side='right').sum()
        count -= (A*A <= x).sum()
        count //= 2

        if count < k:
            left = x
        else:
            right = x

    return str(right)


def __starting_point():
    print((solve(*(open(0).read().splitlines()))))

__starting_point()

from numpy import *
N,K = map(int,input().split())
A = array(sorted(list(map(int,input().split()))))
nega = A[A<0]
zera = A[A==0]
posa = A[0<A]

def cnt(x):
  y = 0
  if x>=0:
    y+=N*len(zera)
  y+=searchsorted(A,x//posa,side="right").sum()
  y+=N*len(nega)-searchsorted(A,-(-x//nega)).sum() 
  y-=len(A[A*A<=x])
  return y//2

r = 10**18
l = -r-1

while r-l>1:
  c=(r+l)//2
  if K<=cnt(c):
    r=c
  else:
    l=c

print(r)

# coding: utf-8
import sys
#from operator import itemgetter
sysread = sys.stdin.readline
read = sys.stdin.read
#from heapq import heappop, heappush
#from collections import defaultdict
sys.setrecursionlimit(10**7)
#import math
#from itertools import combinations
#import bisect# lower_bound etc
import numpy as np
def run():
    N, K, *A = list(map(int, read().split()))
    B = [a for a in A if a>0]
    C = [a for a in A if a<0]
    C_abs = [-c for c in C]
    O = A.count(0)
    B = np.array(sorted(B), dtype= np.int64)
    C = np.array(sorted(C), dtype = np.int64)
    C_abs = np.array(sorted(C_abs), dtype = np.int64)
    n_neg = len(B) * len(C)
    n_0 = O * (O - 1) // 2 + O * (len(B) + len(C))

    def find(x):
        ret = 0
        if x < 0:
            ret += np.searchsorted(C, x//B, side='right').sum()

        elif x == 0:
            ret += n_0 + n_neg
        else:
            ret += n_neg + n_0
            b_count = (B ** 2 <= x).sum()
            c_count = (C ** 2 <= x).sum()
            ret += (np.searchsorted(B, x//B, side='right').sum() - b_count) // 2

            ret += (np.searchsorted(C_abs, x//C_abs, side='right').sum() - c_count) // 2
        return ret

    high = 10 ** 18
    low = -high
    current = 0
    while high - low > 1:
        tmp = find(current)
        if tmp < K:
            low = current
        else:
            high = current

        current = (low + high) // 2

    print(high)

def __starting_point():
    run()
__starting_point()

import numpy as np

N, K = list(map(int, input().split()))
A = np.array(tuple(map(int, input().split())), dtype=np.int64)

A = np.sort(A)
pos = A[A > 0]
neg = A[A < 0]
zero = len(A[A == 0])

def cnt(x):
    """return #{a <= x | a in A}"""
    ret = 0

    if x >= 0:
        ret += zero * N

    ret += np.searchsorted(A, x // pos, side='right').sum()
    ret += (N - np.searchsorted(A, (-x - 1) // (-neg), side='right')).sum()
    ret -= ((A * A) <= x).sum()
    return ret // 2

overEq = 10**18 + 100
less = -10**18 - 100

while less + 1 < overEq:
    mid = (overEq + less) // 2
    if cnt(mid) >= K:
        overEq = mid
    else:
        less = mid

print(overEq)


import sys
import numpy as np

N, K = map(int, sys.stdin.readline().rstrip().split())
A = np.array(sys.stdin.readline().rstrip().split(), np.int64)

# A をソートし、負／ゼロ／正　に分ける
A = np.sort(A)
zero = A[A == 0]
pos = A[A > 0]
neg = A[A < 0]


def f2(x):
    """
    積が x 以下になるペアの個数を返す

    - (i,j) と (j,i), (i,i) の重複を許して後で調整
    - A = [a_0, a_1, a_2, ... ,a_n-1] で、
         負 ～ 0 ～ 正 まで混ざった状態で
         target k と掛け合わせて x 以下になる場所 (index) を探す
    -           \__-5_-1__0_0_...__1___2
      a_0   = -5|  25  5  0 0 ... -5 -10
      a_1   = -1|   5  1  0 0 ... -1  -2
      a_2   =  0|   0  0  0 0 ...  0   0
      a_3   =  0|   0  0  0 0 ...  0   0
      a_4   =  1|  -5 -1  0 0 ...  1   2
      .....     |
      a_n-1 =  2| -10 -2  0 0 ...  2   4
    """

    cnt_tpl = 0

    # k < 0 の掛け合わせ -> 右から
    B = A.copy()
    B = -B
    B.sort()
    cnt_tpl += np.searchsorted(B, x // (-neg), side='right').sum()

    # a_2, a_3, k = 0 なら そのペアはすべて 0 (x//0になるので別扱い)
    if x >= 0:
        cnt_tpl += len(zero) * N

    # k > 0 の掛け合わせ -> 左から何番目まで, x 以下にできるか？
    cnt_tpl += np.searchsorted(A, x // pos, side='right').sum()

    # (i, i) で x 以下になったものがあれば、削除する
    cnt_tpl -= np.count_nonzero(A * A <= x)

    assert cnt_tpl % 2 == 0
    return cnt_tpl // 2


# 二分探索
left = -10 ** 18
right = 10 ** 18
while left + 1 < right:
    x = (left + right) // 2
    if f2(x) >= K:
        right = x
    else:
        left = x


print(right)

import sys
readline=sys.stdin.readline

import numpy as np

N,K=list(map(int,readline().split()))
A=np.array(readline().split(),dtype=int)

nega_list=A[A<0]
posi_list=A[A>0]
zero_num=A[A==0].size

# print(nega_list)
# print(posi_list)
# print(zero_num)

nega_list=np.sort(nega_list)
posi_list=np.sort(posi_list)

nega_cnt=nega_list.size * posi_list.size
posi_cnt=((posi_list.size * posi_list.size-1) // 2) + ((nega_list.size * nega_list.size-1) // 2)

zero_cnt=(zero_num * (zero_num-1)) // 2 + zero_num * (nega_list.size + posi_list.size)

# print(nega_cnt)
# print(posi_cnt)
# print(zero_cnt)


# Kがどこに属するかを判断
if K <= nega_cnt:
  # 負の数が答え
  # かけてX以下になる組み合わせをK個以上作れればOK
  
  def isOkNega(x):
    return np.searchsorted(nega_list,x//posi_list,side="right").sum() >= K
    
  ok=0
  ng=-10**18-1
  while (ok-ng)>1:
    mid=(ok+ng)//2
    if isOkNega(mid):
      ok=mid
    else:
      ng=mid
  print(ok)
  
elif K <= nega_cnt+zero_cnt:
  # 0が答え
  print((0))
  
else:  
  # 正の数が答え
  K-=(nega_cnt+zero_cnt)
  # 正のグループ内の積、負のグループ内の積、それぞれを合わせてX以下の数をK個以上作れる
  
  # 負の数リストは、掛け合わせた絶対値が小さいものを求める必要があるため、正のリストに変更
  nega_list = np.flipud(nega_list * (-1))
  
  # 自分自身との積は除外する必要があるため、自分同士の積リストを作成
  self_nega=nega_list * nega_list
  self_posi=posi_list * posi_list
  
  def isOkPosi(x):
    # print("x",x)
    # 重複を考えずに、負の数同士の積で条件を満たすものをカウント
    nega_all = np.searchsorted(nega_list, x // nega_list, side = "right")
    # print(nega_all)
    # print("self_nega[self_nega <= x]",self_nega[self_nega <= x])
    # 自分自身を掛け合わせたもので、条件を満たすものの個数はカウントから除外する必要がある
    nega_cnt = nega_all.sum() - self_nega[self_nega <= x].size
    # print(nega_cnt)
    
    # 同じペアを二回数えているため1/2する
    nega_cnt //= 2
    
    # 正の数リストで同じことをする
    posi_all = np.searchsorted(posi_list, x // posi_list, side = "right")
    # print(posi_all)
    # print("self_posi[self_posi <= x]",self_posi[self_posi <= x])
    posi_cnt = posi_all.sum() - self_posi[self_posi <= x].size
    # print(posi_cnt)
    posi_cnt //= 2
        
    return nega_cnt + posi_cnt >= K
  
  ok=10**18+1
  ng=0
  while abs(ok-ng)>1:
    mid=abs(ok+ng)//2
    if isOkPosi(mid):
      ok=mid
    else:
      ng=mid
  print(ok)


import numpy as np
from numba import njit
N, K = [int(_) for _ in input().split()]
A = np.array(sorted([int(_) for _ in input().split()]))


@njit
def solve(N, K, A):
    lb = -10**18 - 1
    rb = 10**18 + 1

    def check(x):
        #x以下の積がK個以上ある
        cnt = 0
        for i, a in enumerate(A):
            #区間i2∈[0,i) でA[i]*A[i2]<=xとなるようなi2の個数
            l = 0
            r = i
            if a > 0:
                l = -1
                r = np.searchsorted(A, x // a, side='right')
            elif a < 0:
                l = np.searchsorted(A, 0 - x // (-a), side='left')
                r = N + 1
            elif x < 0:
                r = 0
            l = min(max(l, 0), i)
            r = max(min(r, i), 0)
            cnt += r - l
        return cnt >= K

    # Min x for check(x) == True
    while rb - lb > 1:
        mid = (rb + lb) // 2
        if check(mid):
            rb = mid
        else:
            lb = mid
    print(rb)


solve(N, K, A)


# D - Pairs

import numpy as np

N, K = map(int, input().split())
A = np.array(sorted(list(map(int, input().split()))), np.int64)

n_zero = len(A[A == 0])
A_posi = A[A > 0]
A_nega = A[A < 0]

def n_pairs_less_than_or_equal_to_border(product_border):
    n_pairs = -np.sum(A*A <= product_border) # i==jかつ条件を満たすペアの個数を先に引き、以降重複を許して数える
    n_pairs += n_zero * N * (product_border >= 0)

    n_pairs += np.searchsorted(A, product_border//A_posi, side="right").sum()
    n_pairs += (N - np.searchsorted(A, -(-product_border//A_nega), side="left")).sum()

    # 上記2行は下記と同様の処理だが下記の実装だとTLE
    # for i in range(N):
    #     if A[i] > 0:
    #         n_pairs += np.searchsorted(A, product_border//A[i], side="right")
    #     elif A[i] < 0:
    #         n_pairs += N - np.searchsorted(A, -(-product_border//A[i]), side="left")

    n_pairs //= 2
    return n_pairs


lower = -(10**18)
upper = 10**18

while lower <= upper:
    x = (lower + upper) // 2
    if n_pairs_less_than_or_equal_to_border(x) >= K:
        ans = x
        upper = x - 1
    else:
        lower = x + 1

print(ans)

import numpy as np
n,k = list(map(int,input().split()))
a = np.array(list(map(int,input().split())))
a.sort()

p = a[a>0]
zeros = np.count_nonzero(a==0)
m = a[a<0]

#数xが何番目に大きい積か計算。複数ある場合は最大値
def count(x):
  cnt = 0
  #0以上だったらまず0の個数を足す
  if x >= 0:
    cnt += zeros*n #同じ要素の２じょうはあとで除くのでここでは気にせずかける
  #プラス部分のカウント
  #x//pはpをかけてもxを超えない数
  cnt += a.searchsorted(x//p,side='right').sum()
  #マイナス部分のカウント
  #マイナスは書けると大小が逆転する
  cnt += n*len(m) - a.searchsorted(-(-x//m),side='left').sum()
  #二乗を引く
  cnt -= np.count_nonzero(a*a<=x)
  return cnt//2

#十分に大きい範囲
l,r = -10**19,10**19
#r==lになるまで
while r-l>1:
  mid = (r+l)//2
  #真ん中がk以上だったらrを小さくして再挑戦
  if count(mid) >= k:
    r = mid
  else:
    l = mid
print(r)

  


import numpy as np
n, k = list(map(int, input().split()))
a = np.array(list(map(int, input().split())))
pos = np.sort(a[a>0])
neg = np.sort(np.abs(a[a<0]))
zero = (a==0).sum()

INF = 2*(10**18)
l = -INF
r = INF

while(r-l>1):
    mid = (l+r)//2
    cnt = 0
    if mid >= 0:
        cnt = len(pos)*len(neg)  #(+) * (-)
        cnt += (len(pos)+len(neg)) * zero # 0 * (non-zero)
        cnt += (zero*(zero-1))//2 # 0 * 0
        x = np.searchsorted(pos, mid//pos, side='right').sum() #(+) * (+)
        x += np.searchsorted(neg, mid//neg, side='right').sum() #(-) * (-)
        x -= (pos*pos<=mid).sum()
        x -= (neg*neg<=mid).sum()
        cnt += x/2
    else:
        #積がmid以上になれば良い -> midよりも小さい
        cnt = (len(neg) - np.searchsorted(neg, abs(mid)//pos + (mid%pos!=0), side='left')).sum()
    #print(mid, cnt)
    #cnt := 積がmid以下になる物の数
    #k番目の数　-> それ以下のものがk個以上ある事が必要
    #cntがk個よりも少ない -> 条件を満たしていない
    #cntがそれ以上ならok
    if cnt < k:
        l = mid
    else:
        r = mid
print(r)


# coding: utf-8
import sys
import numpy as np

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

# neg, zero, posに分けて、二分探索
N, K = lr()
A = np.array(lr()); A.sort()
neg = A[A<0]
zero = A[A==0]
pos = A[A>0]

def check(x):
    '''x以下の積がK個以上あるならTrueを返す'''
    cnt = 0  # 最後に２でわる
    if x >= 0:
        cnt += len(zero) * N
    cnt += (np.searchsorted(A, x//pos, side='right')).sum()
    cnt += (N - np.searchsorted(A, (-x-1)//(-neg), side='right')).sum()
    cnt -= np.count_nonzero(A*A <= x)
    assert cnt % 2 == 0
    return (cnt//2) >= K

ok = 10**18; ng = -10**18-1
while abs(ng-ok) > 1:
    mid = (ok+ng) // 2
    if check(mid):
        ok = mid
    else:
        ng = mid

print(ok)
# 30


import numpy as np
n,k=list(map(int,input().split()))
a=np.array(list(map(int,input().split())))
a.sort()
p=a[a>0]
z=np.count_nonzero(a==0)
m=a[a<0]
r=10**19
l=-r
while r-l>1:
    # 区間[l,r]を半分に分けて探索。最終的にrが求める値になるようにする。
    # b以下のものがk個以上あるような、最小のbを求める。bを大きくする→b以下のものも増える。b以下のものがめちゃくちゃある→bを減らす。
    b=(l+r)//2
    c=0
    if b>=0:
        c+=z*n
    # 配列aに対し、配列b//pの要素たちをそれぞれsearchsortedする。結果の配列はb//pと同じ形になる。
    c+=a.searchsorted(b//p,side='right').sum()
    # 配列aに対し、配列b//mの要素たちをそれぞれsearchsortedする。結果の配列はb//mと同じ形になる。
    c+=n*len(m)-a.searchsorted(-(-b//m),side='left').sum()
    c-=np.count_nonzero(a*a<=b)
    if c//2>=k:
        r=b
    else:
        l=b
print(r)


import numpy as np

from bisect import bisect

DEBUG = False


def bisect_f(f, lo, hi):
    if DEBUG:
        assert f(lo) and not f(hi)
    while hi - lo > 1:
        mid = (lo + hi) // 2
        if f(mid):
            lo = mid
        else:
            hi = mid
        if DEBUG:
            assert f(lo) and not f(hi)
    if DEBUG:
        assert hi - lo == 1
        assert f(lo) and not f(hi)
    return lo


N, K = list(map(int, input().split()))
A = list(map(int, input().split()))
A.sort()
neg = []
zero = []
pos = []
for x in A:
    if x < 0:
        neg.append(x)
    elif x == 0:
        zero.append(x)
    else:
        assert x > 0
        pos.append(x)

revAbsNeg = [-x for x in reversed(neg)]  # Reverse neg and keep magnitude only
posSq = [x ** 2 for x in pos]
negSq = [x ** 2 for x in revAbsNeg]

pos = np.array(pos, dtype=np.int64)
revAbsNeg = np.array(revAbsNeg, dtype=np.int64)


def countDistinctPairsLessThan(arr, prod):
    # Given a sorted array find the number of pairs that are < prod
    # O(N * log(N)) where N = len(arr)

    N = arr.shape[0]
    assert arr.shape == (N,)
    count3 = np.sum(
        np.minimum(np.arange(N), np.searchsorted(arr, (prod - 1) // arr, side="right"))
    )

    if DEBUG:
        count = 0
        for i, x in enumerate(arr):
            count += bisect(arr, (prod - 1) // x, 0, i)

        count2 = 0
        for i in range(len(arr)):
            for j in range(i + 1, len(arr)):
                if arr[i] * arr[j] < prod:
                    count2 += 1

        print((count, count2, count3))
        assert count == count2 == count3
    return count3


def countPairsLessThanOrEqual(arr1, arr2, prod):
    # Given two sorted arrays containing *positive* numbers only,
    # find the number of pairs between the two arrays that are <= prod
    # O(N * log(M)) where N = len(arr1), M = len(arr2)
    if len(arr1) > len(arr2):
        arr1, arr2 = arr2, arr1

    count3 = np.sum(np.searchsorted(arr2, prod // arr1, side="right"))

    if DEBUG:
        count = 0
        for x in arr1:
            count += bisect(arr2, prod // x)
        count2 = 0
        for x in arr1:
            for y in arr2:
                if x * y <= prod:
                    count2 += 1
        assert count == count2 == count3
    return count3


def getIndex(prod):
    # Count number of pairs strictly less than prod
    count = 0
    if prod < 0:
        # All negatives except for the negatives with abs value less than or equal -prod
        count += len(pos) * len(neg)
        count -= countPairsLessThanOrEqual(pos, revAbsNeg, -prod)
    elif prod >= 0:
        # All negatives
        count += len(pos) * len(neg)
        if prod > 0:
            # All zeroes
            count += len(zero) * len(neg)
            count += (len(zero) * (len(zero) - 1)) // 2
            count += len(zero) * len(pos)
            # Positives with positives
            count += countDistinctPairsLessThan(pos, prod)
            # Negatives with negatives
            count += countDistinctPairsLessThan(revAbsNeg, prod)

    if DEBUG:
        count2 = 0
        for i in range(N):
            for j in range(i + 1, N):
                if A[i] * A[j] < prod:
                    count2 += 1
        assert count == count2
    return count


def solve(K):
    lo = -10 ** 18
    hi = 10 ** 18 + 1
    if DEBUG:
        assert getIndex(lo) <= K < getIndex(hi)
    prod = bisect_f(lambda prod: getIndex(prod) <= K, lo, hi)
    if DEBUG:
        assert getIndex(prod) <= K < getIndex(prod + 1)
    return prod


if DEBUG:
    for k in range((N * (N - 1)) // 2):
        print(("k", k, solve(k)))

print((solve(K - 1)))  # K is 1-indexed



import numpy as np
n,k=map(int,input().split())
a=list(map(int,input().split()))
a.sort()
a = np.array(a,dtype="int64")
a_minus = a[a<0]
a_plus = a[a>0]
a_zero = a[a==0]
#print(a_plus)
l = - 10**19
r = 10**19


while r - l > 1:
  mid = (l+r)//2
  # mid以下の個数を調べる
  cnt = 0
  # 正の数の組み合わせでmid以下の個数を調べる
  cnt += a.searchsorted(mid//a_plus, side="right").sum()
  # 負の数で同様
  cnt += (n - a.searchsorted((-mid-1)//(-a_minus), side="right")).sum()
  # 同じ数の組み合わせ(差し引くよう)
  cnt -= np.count_nonzero(a*a<=mid)
  # ゼロも同様(mid>=0のときのみ)
  cnt += len(a_zero)*n if mid >= 0 else 0
  
  # 重複を割る
  cnt //= 2
  
  if cnt >= k:
    r = mid
  else:
    l = mid
  
print(r)

import numpy as N
n,k=map(int,input().split())
A=N.array(list(map(int,input().split())))
A.sort()
p=A[A>0]
z=N.count_nonzero(A==0)
m=A[A<0]
r=10**19
l=-r
while r-l>1:
    b=(l+r)//2
    c=0
    if b>=0:
        c+=z*n
    c+=A.searchsorted(b//p,side='right').sum()
    c+=n*len(m)-A.searchsorted(-(-b//m),side='left').sum()
    c-=N.count_nonzero(A*A<=b)
    if c//2>=k:
        r=b
    else:
        l=b
print(r)

import numpy as np
N, K = list(map(int, input().split()))

A = np.array(list(map(int, input().split())))
A.sort()

pos = A[A > 0]
neg = A[A < 0]
zero = A[A == 0]

l = -10**18
r = 10**18

while l + 1 < r:
    x = (l+r) // 2
    cnt = 0
    if x >= 0:
        cnt += N * len(zero)

    cnt += A.searchsorted(x//pos, side="right").sum()
    cnt += (N - A.searchsorted(-(-x//neg), side="left")).sum()
    cnt -= np.count_nonzero(A * A <= x)
    cnt //= 2

    if cnt >= K:
        r = x
    else:
        l = x

print(r)




import numpy as np
def f(nums, a):
  return 0  if nums.size<=1 else (np.searchsorted(nums, a//nums, side='right').sum()-np.searchsorted(nums, int(pow(a, 1/2)), side='right'))//2

N, K=map(int, input().split())
A=np.sort(list(map(int, input().split())))

p=np.sum(A>0)
q=np.sum(A<0)
Z=N-p-q
AP=A[-p:] if p>0 else np.array([])
AN=A[:q] if q>0 else np.array([])

b=(N-Z)*Z+Z*(Z-1)//2
a=p*q

if K<=a:
  x=AP[-1]*AN[0]-1
  y=AP[0]*AN[-1]
  while y-x>1:
    tmp=(y+x)//2
    counter=np.searchsorted(AN, tmp//AP, side='right').sum()
    if counter<K:
      x=tmp
    else:
      y=tmp
  print(y)
elif K<=a+b:
  print(0)
else:
  if q>1:
    AN=-AN[::-1]
  x=0
  y=10**18
  K=K-a-b
  while y-x>1:
    tmp=(y+x)//2
    if f(AP, tmp)+f(AN, tmp)<K:
      x=tmp
    else:
      y=tmp
  print(y)

N,K=map(int, input().split())
A=list(map(int, input().split()))
A=sorted(A)
import numpy as np
A=np.array(A,dtype="int64")
Z=A[A==0]
H=A[A<0]
S=A[A>0]
l,r=-10**19,10**19
while r-l>1:
  mid=(r+l)//2
  cnt=0
  cnt+=A.searchsorted(mid//S,side="right").sum()
  cnt+=(N-A.searchsorted((-mid-1)//(-H),side="right")).sum()
  cnt-=np.count_nonzero(A*A<=mid)
  if mid>=0:
    cnt+=len(Z)*N 
  cnt//=2
  if cnt>=K:
    r=mid
  else:
    l=mid 
print(r)

import numpy as np
 
N,K=list(map(int, input().split()))
A=np.sort(np.array(input().split(),np.int64))
z=A[A==0]
p=A[A>0]
n=A[A<0]
 
def f(x):
 cnt=0
 if x>=0:
  cnt+=len(z)*N
 cnt+=np.searchsorted(A,x//p,side='right').sum()
 cnt+=(N-np.searchsorted(A,(-x-1)//(-n),side='right')).sum()
 cnt-=np.count_nonzero(A*A<=x)
 assert cnt%2==0
 return cnt//2
 
l=-10**18
r=10**18
while l+1<r:
 x=(l+r)//2
 if f(x)>=K:
  r=x
 else:
  l=x
print(r)


import sys
#sys.setrecursionlimit(10**9)
input = sys.stdin.readline

import numpy as np

n, k = list(map(int, input().split()))
A = np.array(input().split(), np.int64)
A = np.sort(A)

P = A[A>0]
Z = A[A==0]
N = A[A<0]

#t = n*(n-1)//2

def ok(x):
    # x以下になる組み合わせがk個以上
    cnt = 0
    #cnt += np.searchsorted(A, np.ceil(x/P), side='right').sum()
    cnt += np.searchsorted(A, x//P, side='right').sum()
    #cnt += n-np.searchsorted(A, np.floor(x/N), side='left').sum()
    cnt += (n-np.searchsorted(A, (-x-1)//(-N), side='right')).sum()
    if x >= 0:
        cnt += len(Z)*n
    cnt -= np.count_nonzero(A*A <= x)
    cnt = cnt//2
    if cnt >= k:
        return True
    else:
        return False

l = -10**18-1
r = 10**18+1
while l+1 < r:
    c = (l+r)//2
    if ok(c):
        r = c
    else:
        l = c
print(r)


import numpy as np


def get_Negative(K, pos, neg):
    K = len(pos) * len(neg) - K + 1
    l = 0
    r = 10 ** 18 + 10
    while r - l > 1:
        m = (l + r) // 2
        target = m // pos
        x = np.searchsorted(neg, target, side="right").sum()
        if x >= K:
            r = m
        else:
            l = m
    return -r


def get_Positive(K, pos, neg):
    l = 0
    r = 10 ** 18 + 10
    tmp_pos = np.arange(len(pos))
    tmp_neg = np.arange(len(neg))
    while r - l > 1:
        m = (r + l) // 2
        cnt = 0
        if len(pos) > 1:
            t1 = m // pos
            x1 = np.searchsorted(pos, t1, side="right")
            x1 = np.maximum(0, x1 - tmp_pos - 1)
            cnt += x1.sum()
        if len(neg) > 0:
            t2 = m // neg
            x2 = np.searchsorted(neg, t2, side="right")
            x2 = np.maximum(0, x2 - tmp_neg - 1)
            cnt += x2.sum()
        if cnt >= K:
            r = m
        else:
            l = m
    return r


def main():
    N, K = map(int, input().split())
    A = np.array(input().split(), dtype=np.int64)

    positive = A[A > 0]
    negative = -A[A < 0]
    positive.sort()
    negative.sort()

    Npos = len(positive)
    Nneg = len(negative)
    Nzero = N - Npos - Nneg

    P_neg = Npos * Nneg
    P_pos = 0
    if Npos:
        P_pos += Npos * (Npos - 1) // 2
    if Nneg:
        P_pos += Nneg * (Nneg - 1) // 2
    P_zero = N * (N - 1) // 2 - P_pos - P_neg

    if K <= P_neg:
        ans = get_Negative(K, positive, negative)
        return ans
    K -= P_neg
    if K <= P_zero:
        return 0
    K -= P_zero
    ans = get_Positive(K, positive, negative)
    return ans


def __starting_point():
    print(main())
__starting_point()

import numpy as np
N,K = [int(i) for i in input().split(' ')]

A = np.array([int(i) for i in input().split(' ')])

A.sort()
zero = A[A==0]
minus = A[A<0]
plus = A[A>0]

def index_count(x):
    cnt = 0
    if x >= 0:
        cnt += len(zero) * N
    cnt += np.searchsorted(A,x//plus,side='right').sum()
    cnt += (N - np.searchsorted(A,-(-x//minus),side='left')).sum()
    cnt -= np.count_nonzero(A*A <= x)

    assert cnt % 2 == 0
    return cnt //2


left = -10**18
right = 10**18

while left + 1 < right:
    mid = (left +right) //2
    a = index_count(mid)
    if a >= K:
        right = mid
    else:
        left = mid

print(right)

import numpy as np


def partsolve(A, x, positive, zero, negative):
    """
    :param A:
    :param x:
    :return: Aの積のペアの中で、x以下となるペアの個数
    """
    count = 0
    if x >= 0:
        count = len(zero) * len(A)
    P = x // positive
    Pc = np.searchsorted(A, P, side='right')
    count += Pc.sum()

    N = (-x-1) // -negative
    Nc = np.searchsorted(A, N, side='right')
    Nc = len(A) - Nc
    count += Nc.sum()

    count -= np.count_nonzero(A * A <= x)
    return count // 2

def solve(N, K, As):
    A = np.array(sorted(As), np.int64)
    positive = A[A > 0]
    zero = A[A == 0]
    negative = A[A < 0]

    left = -10 ** 18
    right = 10 ** 18
    while right - left > 1:
        mid = left + (right - left) // 2
        c = partsolve(A, mid, positive, zero, negative)
        if c < K:
            left = mid
        else:
            right = mid
    return right



def __starting_point():
    N, K = tuple(map(int, input().split(" ")))
    As = list(map(int, input().split(" ")))
    print((solve(N, K, As)))


__starting_point()

import sys
import numpy as np


TEST_INPUT = [
    """
    4 3
    3 3 -4 -2
    """,
    """
    10 40
    5 4 3 2 -1 0 0 0 0 0
    """,
    """
    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
    """
]
ANSWER = [
    "-6",
    "6",
    "448283280358331064"
]


class InputHandler:

    def __init__(self, text_lines="", is_test=False):
        self.data = list(text_lines.split("\n"))
        self.index = 0
        self.is_test = is_test

    def input(self):
        if self.is_test:
            self.index += 1
            return self.data[self.index].strip()
        else:
            return sys.stdin.readline().rstrip()


def query(a, n, a_arr_p, a_arr_n, n_zeros, k):

    # return (num of pairs <= a) < k

    if a >= 0:
        # negative
        res = len(a_arr_p) * len(a_arr_n)
        # zero
        res += n_zeros * (n - n_zeros) + n_zeros * (n_zeros - 1) // 2
        # p * p
        res_pp = np.searchsorted(a_arr_p, a // a_arr_p, side="right").sum()
        res_pp -= (a_arr_p * a_arr_p <= a).sum()
        res += res_pp // 2
        # n * n
        res_nn = np.searchsorted(a_arr_n, a // a_arr_n, side="right").sum()
        res_nn -= (a_arr_n * a_arr_n <= a).sum()
        res += res_nn // 2
    else:
        # p * n
        res = len(a_arr_p) * len(a_arr_n) - np.searchsorted(a_arr_n, (a_arr_p - a - 1) // a_arr_p, side="left").sum()
    # print(a, res)
    if res >= k:
        return True
    else:
        return False


def solve(n, k, a_list):

    left = - 10 ** 18 - 1
    right = 10 ** 18 + 1
    center = 0

    a_arr = np.array(a_list)

    a_arr_p = a_arr[a_arr > 0]
    a_arr_n = - a_arr[a_arr < 0]
    n_zeros = (a_arr == 0).sum()
    a_arr_p.sort()
    a_arr_n.sort()

    while left<right:
        center=(left+right)//2
        if query(center, n, a_arr_p, a_arr_n, n_zeros, k):
            right=center
        else:
            left=center+1

    return right


def input_and_solve(ih):
    n, k = list(map(int, ih.input().split()))
    a_list = list(map(int, ih.input().split()))
    res = solve(n, k, a_list)
    return res


def main():
    ih = InputHandler()
    res = input_and_solve(ih)
    print(res)


def test():
    for test_input, ans in zip(TEST_INPUT, ANSWER):
        ih = InputHandler(test_input, True)
        res = input_and_solve(ih)
        # print(res, ans)
        assert str(res) == str(ans)


def __starting_point():
    #test()
    main()

__starting_point()

import numpy as np

N, K=map(int, input().split())
A=np.sort(list(map(int, input().split())))

p=np.sum(A>0)
q=np.sum(A<0)
Z=N-p-q
if p>0:
  AP=A[-p:]
else:
  AP=[]
if q>0:
  AN=A[:q]
else:
  AN=[]

b=(N-Z)*Z+Z*(Z-1)//2
a=p*q

if K<=a:
  x=AP[-1]*AN[0]-1
  y=AP[0]*AN[-1]
  while y-x>1:
    tmp=(y+x)//2
    counter=np.searchsorted(AN, tmp//AP, side='right').sum()
    if counter<K:
      x=tmp
    else:
      y=tmp
  print(y)
elif K<=a+b:
  print(0)
else:
  x=0
  y=10**18
  K=K-a-b
  if q<=1:
    while y-x>1:
      tmp=(y+x)//2
      counter=(np.searchsorted(AP, tmp//AP, side='right').sum()-np.searchsorted(AP, int(pow(tmp, 1/2)), side='right'))//2
      if counter<K:
        x=tmp
      else:
        y=tmp
    print(y)
    return
    
  AN=AN[::-1]
  AN=-AN
  
  if p<=1:
    while y-x>1:
      tmp=(y+x)//2
      counter=(np.searchsorted(AN, tmp//AN, side='right').sum()-np.searchsorted(AN, int(pow(tmp, 1/2)), side='right'))//2
      if counter<K:
        x=tmp
      else:
        y=tmp
    print(y)
    return
    
  while y-x>1:
    tmp=(y+x)//2
    counter1=(np.searchsorted(AP, tmp//AP, side='right').sum()-np.searchsorted(AP, int(pow(tmp, 1/2)), side='right'))//2
    counter2=(np.searchsorted(AN, tmp//AN, side='right').sum()-np.searchsorted(AN, int(pow(tmp, 1/2)), side='right'))//2
    counter=counter1+counter2
    if counter<K:
      x=tmp
    else:
      y=tmp
  print(y)

import numpy as np
n,k=map(int,input().split())
a=np.sort(np.array(input().split(),'int64'))

plus=a[a>0]
zeros=np.sum(a==0)
minus=a[a<0]

def counter(T):
  c=0
  if T>=0:
    c+=zeros*n
  c+=np.searchsorted(a,T//plus,side='right').sum()
  c+=(n-np.searchsorted(a,(-T-1)//(-minus),side='right')).sum()
  c-=np.count_nonzero(a*a<=T)
  return c//2

left=-10**18
right=10**18
while abs(right-left)>1:
  mid=(left+right)//2
  if counter(mid)>=k:
    right=mid
  else:
    left=mid
print(right)

# https://maspypy.com/atcoder-%E5%8F%82%E5%8A%A0%E6%84%9F%E6%83%B3-2019-02-16abc-155
import numpy as np

N, K = list(map(int, input().split()))
A = np.array(list(map(int, input().split())))
A.sort()
G = A[A > 0]
Z = A[A == 0]
L = A[A < 0]

ok = 10 ** 18 + 1
ng = -10 ** 18 - 1

# x以下がK個以上であるxの最小値

while ok - ng > 1:
    mid = (ng + ok) // 2
    # mid以下のペアの個数を数える

    # 正のもののうち、mid以下のペアの個数を数える
    cg = np.searchsorted(A, mid // G, side="right").sum()

    # 負のもののうちmid以下のペアの個数を数える
    cl = (N - np.searchsorted(A, (-mid - 1) // (-L), side="right")).sum()

    # 同じ数字同士の積がmid以下のものを数える
    d = np.count_nonzero(A * A <= mid)

    # 0がmid以下なら、それもプラスするために必要
    z = 0
    if mid >= 0:
        z += len(Z) * N

    c = cg + cl + z - d

    # 二重になっているので、割る
    c //= 2

    # mid以下のペアの個数がK個以上のとき
    if c >= K:
        ok = mid
    else:
        ng = mid

print(ok)


import sys
readline=sys.stdin.readline

import numpy as np

N,K=list(map(int,readline().split()))
A=np.array(readline().split(),dtype=int)

nega_list=A[A<0]
posi_list=A[A>0]
zero_num=A[A==0].size

nega_list=np.sort(nega_list)
posi_list=np.sort(posi_list)

nega_cnt=nega_list.size * posi_list.size
posi_cnt=((posi_list.size * posi_list.size-1) // 2) + ((nega_list.size * nega_list.size-1) // 2)

zero_cnt=(zero_num * (zero_num-1)) // 2 + zero_num * (nega_list.size + posi_list.size)

# Kがどこに属するかを判断
if K <= nega_cnt:
  # 負の数が答え
  # かけてX以下になる組み合わせをK個以上作れればOK
  
  def isOkNega(x):
    return np.searchsorted(nega_list,x//posi_list,side="right").sum() >= K
    
  ok=0
  ng=-10**18-1
  while (ok-ng)>1:
    mid=(ok+ng)//2
    if isOkNega(mid):
      ok=mid
    else:
      ng=mid
  print(ok)
  
elif K <= nega_cnt+zero_cnt:
  # 0が答え
  print((0))
  
else:  
  # 正の数が答え
  K-=(nega_cnt+zero_cnt)
  # 正のグループ内の積、負のグループ内の積、それぞれを合わせてX以下の数をK個以上作れる
  
  # 負の数リストは、掛け合わせた絶対値が小さいものを求める必要があるため、正のリストに変更
  nega_list = np.flipud(nega_list * (-1))
  
  # 自分自身との積は除外する必要があるため、自分同士の積リストを作成
  self_nega=nega_list * nega_list
  self_posi=posi_list * posi_list
  
  def isOkPosi(x):
    # 重複を考えずに、負の数同士の積で条件を満たすものをカウント
    nega_all = np.searchsorted(nega_list, x // nega_list, side = "right")
    
    # 自分自身を掛け合わせたもので、条件を満たすものの個数はカウントから除外する必要がある
    nega_cnt = nega_all.sum() - self_nega[self_nega <= x].size
    
    # 同じペアを二回数えているため1/2する
    nega_cnt //= 2
    
    # 正の数リストで同じことをする
    posi_all = np.searchsorted(posi_list, x // posi_list, side = "right")
    posi_cnt = posi_all.sum() - self_posi[self_posi <= x].size
    posi_cnt //= 2
        
    return nega_cnt + posi_cnt >= K
  
  ok=10**18+1
  ng=0
  while abs(ok-ng)>1:
    mid=abs(ok+ng)//2
    if isOkPosi(mid):
      ok=mid
    else:
      ng=mid
  print(ok)


import numpy as np

n, k = map(int, input().split()) 
a_list = np.array(list(map(int, input().split())))

a_list.sort()

zero_list = a_list[a_list == 0]
minus_list = a_list[a_list < 0]
plus_list = a_list[a_list > 0]

def index_count(x):
    cnt = 0
    if x >= 0:
        cnt += len(zero_list) * n
    cnt += np.searchsorted(a_list, x // plus_list, side='right').sum()
    cnt += (n - np.searchsorted(a_list, -(-x // minus_list), side='left')).sum()
    cnt -= np.count_nonzero(a_list * a_list <= x)
 
    assert cnt % 2 == 0
    return cnt // 2
 
 
left = -10**18
right = 10**18
 
while left + 1 < right:
    mid = (left + right) // 2
    a = index_count(mid)
    if a >= k:
        right = mid
    else:
        left = mid
 
print(right)

# https://maspypy.com/atcoder-%E5%8F%82%E5%8A%A0%E6%84%9F%E6%83%B3-2019-02-16abc-155#toc3
# https://atcoder.jp/contests/abc155/submissions/10152895
# 写経


# 条件を満たす要素を抽出
# ndarray[条件式]

def binary_search(*, ok, ng, func):
    while abs(ok - ng) > 1:
        mid = (ok + ng) // 2
        if func(mid):
            ok = mid
        else:
            ng = mid
    return ok


def main():
    import sys
    import numpy as np

    inf = 10 ** 18 + 1
    input = sys.stdin.readline

    N, K = list(map(int, input().split()))
    A = np.array(input().split(), dtype=np.int64)

    A.sort()

    zero = A[A == 0]
    pos = A[A > 0]
    neg = A[A < 0]

    def count(x):
        """
        定数cに対して Ai*Aj<=c となる(i,j)の数え上げ
        順序制約 i<j -> 順序制約のない(i,j)からi==jの場合の個数を引いて2で割る
        iを固定して a=Ai とする
        a=0
            ax=0(<=c?),解なしまたは任意のx
        a>0
            ax<=c
            <-> x<=c/a
            <-> x<=c//a
        a<0
            ax<=c
            <-> (-a)x>=(-c)

            否定をとり,aの対候補全体=Nから引く

            (-a)x<(-c)
            <-> (-a)x<=(-c-1)
            <-> x<=(-c-1)//(-a)
        """
        cnt = 0
        if x >= 0:
            cnt += zero.size * N  # (a:=0)*v<=x
        cnt += np.searchsorted(a=A, v=x // pos, side='right').sum()  # (a:>0)*v<=x
        cnt += (N - np.searchsorted(a=A, v=(-x - 1) // (-neg), side='right')).sum()  # (a:<0)*v<=x
        cnt -= ((A * A) <= x).sum()  # i==j
        assert cnt % 2 == 0
        return cnt // 2

    ans = binary_search(
        ng=-inf,
        ok=inf,
        func=lambda x: count(x) >= K
    )

    print(ans)


def __starting_point():
    main()

__starting_point()

import numpy as np
# in your code
def p(*args, **kargs):
    if DBG:print(*args, **kargs)
read = input 
rn = lambda :list(map(int, read().split()))
debug = False
def sol(A):
    A = np.array(A, np.int64)
    A = np.sort(A)
    _A = np.sort(-A)

    pos = A[A>0]
    neg = A[A<0]
    zero = A[A==0]
    def searchsorted(*args, **kargs):
        ret = np.searchsorted(*args, **kargs)

#         print(args, kargs)
#         print(ret)
        return ret

    # python 保证余数>0，即，整除，向无穷小round。
    # <= x，pairs that <= x
    def  f(x):
        ret = 0
        if x >= 0:
            ret += len(zero) * len(A)
            ret += searchsorted(A, x//pos, side="right").sum()
            ret += searchsorted(_A, x//(-neg), side="right").sum()
        else :
            ret += searchsorted(A, x//pos,  side="right").sum()
            ret += searchsorted(_A, x//(-neg),  side="right").sum()

        ret -= np.count_nonzero(A*A<=x)
        assert ret % 2 == 0
        return ret // 2
        if debug: print(pos, neg, zero)
    return f

f = sol([-4, -2, 3, 3 ])
assert f(-12) == 2
assert f(-6) == 4 # or 3
# 二分搜索
def bs(A, index):
    A = np.array(A, np.int64)
    f = sol(A)
    max_ele = max(abs(A))

    right = max_ele * max_ele + 1
    left  = - right
    while left + 1 < right:
        middle = (left + right)//2
        m_index = f(middle)
        if debug : print(middle, m_index, left, right, sep="\t")
        if index <= m_index:
            right = middle
        else :
            left = middle
    return right

n,index = rn()
A = np.array(read().split(), np.int64)
print(bs(A, index))


import numpy as np
from numba import njit


@njit
def main(I):
    N,K=I[0],I[1]
    A = I[2:]
    A.sort()
    lb = -10**18-1
    rb = 10 ** 18 + 1
    while rb - lb > 1:
        target = (rb + lb) // 2
        if 1:
            cnt=0
            for i, a in enumerate(A):
                if a==0:
                    d = i if target >= 0 else 0
                elif a < 0:
                    il = np.searchsorted(A,0- (-target)//a,side='left')
                    d = max(i - il, 0)
                else:
                    ir = np.searchsorted(A,target//a,side='right')
                    d = min(ir, i)
                cnt+=d
        if cnt>=K:
            rb = target
        else:
            lb = target
    return rb

I=np.array([int(_) for _ in open(0).read().split()],dtype=int)
print(main(I))

import numpy as np

n, k = [int(i) for i in input().split()]
a = np.array(sorted([int(i) for i in input().split()]))
posi = a[a > 0]
zero = a[a == 0]
nega = a[a < 0]

# 2分探索, mid より小さいものを数える
l = -10 ** 18 - 1
r = 10 ** 18 + 1
while r - l > 1:
    mid = (r + l) // 2
    cnt = 0
    if mid >= 0:
        cnt += len(zero) * n

    cnt += a.searchsorted(mid // posi, side="right").sum()
    cnt += (n - a.searchsorted(-(-mid // nega), side="left")).sum()
    cnt -= np.count_nonzero(a * a <= mid)
    cnt //= 2
    if cnt >= k:
        r = mid
    else:
        l = mid
print(r)


import numpy as np

N, K = list(map(int,input().split()))
A = np.array(list(map(int,input().split())))
A.sort()
posi = A[A > 0]
zero = A[A == 0]
nega = A[A < 0]

# 積がx以下の組を求める
def check(x):
    count = 0  # 積がx以下の組
    if x >= 0:
        count += len(zero) * N  # zero * N
    count += np.searchsorted(A, x // posi, side = 'right').sum()  # posi * N
    count += (N - np.searchsorted(A, (-x - 1) // (-nega), side = 'right')).sum()  # nega * N
    count -= np.count_nonzero(A * A <= x)  # 自分自身との組
    return count // 2  #重複を消す

# 二分探索
low = -10 ** 18
high = 10 ** 18
while low + 1 < high:
    mid = (low + high) // 2
    if check(mid) < K:  # OK
        low = mid
    else:               # NG
        high = mid

print(high)


import numpy as np

n,k=list(map(int,input().split()))
A=np.array(input().split(),np.int64)
A.sort()

zero=A[A==0]
neg=A[A<0]
pos=A[A>0]

def f(x): # count pairs x or less
    cnt=0
    #zero
    if x>=0:
        cnt += len(zero)*n
    #pos
    cnt += A.searchsorted(x//pos,side="right").sum()
    #neg
    cnt += (n-A.searchsorted(-(-x//neg),side="left")).sum()
    #except a*a
    cnt-=np.count_nonzero(A*A<=x)
    return cnt//2

l=-10**18
r=10**18

while l<r:
    pov=(l+r)//2
    if f(pov)>=k:
        r=pov
    else:
        l=pov+1
print(l)


import numpy as np
N,K = map(int,input().split())
a = np.array(input().split(),np.int64)
a = np.sort(a)
zero = a[a==0]
pos = a[a>0]
neg = a[a<0]

def f(x):
    count = 0
    c = x // pos
    count += np.searchsorted(a, c, side='right').sum()
    count += N*len(zero) if x >= 0 else 0
    c = -(-x // neg)
    count += (N - np.searchsorted(a, c, side='left')).sum()
    count -= a[a*a <= x].size
    count //= 2
    return count

right = 10**18
left = -10**18
while right-left>1:
    mid = (right + left)//2
    if f(mid)<K:
        left = mid
    else:
        right = mid
        
print(right)

import numpy as np
n,k=map(int,input().split())
a=np.array(list(map(int,input().split())))
a.sort()
p=a[a>0]
z=a[a==0]
m=a[a<0]
l=-10**18
r=10**18
while r-l>1:
  mid=(r+l)//2
  cnt=0
  if mid>=0:
    cnt+=len(z)*n
  cnt+=a.searchsorted(mid//p,side='right').sum()
  cnt+=(n-a.searchsorted(-(-mid//m),side='left')).sum()
  cnt-=np.count_nonzero(a*a<=mid)
  cnt//=2
  if cnt>=k:
    r=mid
  else:
    l=mid
print(r)

N,K=list(map(int, input().split()))
A=list(map(int, input().split()))
A=sorted(A)
import numpy as np
A=np.array(A,dtype="int64")
Z=A[A==0]
H=A[A<0]
S=A[A>0]
l,r=-10**19,10**19
while r-l>1:
  mid=(r+l)//2
  cnt=0
  cnt+=A.searchsorted(mid//S,side="right").sum()
  cnt+=(N-A.searchsorted((mid+1)//(H),side="right")).sum()
  cnt-=np.count_nonzero(A*A<=mid)
  if mid>=0:
    cnt+=len(Z)*N 
  cnt//=2
  if cnt>=K:
    r=mid
  else:
    l=mid 
print(r)


import numpy as np

n, k = list(map(int, input().split()))
a = list(map(int, input().split()))

a = np.array(a)
a.sort()

nega = a[a<0]
zero = a[a==0]
posi = a[a>0]

l = -10**18-1
r = 10**18+1
while r - l > 1:
   mid = (r+l)//2
   cnt = 0
   if mid >= 0:
      cnt += len(zero)*n
   cnt += a.searchsorted(mid//posi, side='right').sum()
   cnt += (n - a.searchsorted(-(-mid//nega), side='left')).sum()
   cnt -= np.count_nonzero(a*a <= mid)
   cnt //=2
   if cnt >= k:
      r = mid
   else:
      l= mid

print(r)


from sys import stdin
import numpy as np
def main():
    #入力
    readline=stdin.readline
    n,k=map(int,readline().split())
    a=np.array(readline().strip().split(),dtype="int64")
    
    a.sort()
    neg=a[a<0]
    neg_p=neg**2
    zero=a[a==0]
    pos=a[a>0]
    pos_p=pos**2
    l=-10**18-1
    r=10**18
    while l<r-1:
        x=(l+r)//2
        cnt=0
        if neg.size>0:
            cnt+=(a.size-np.searchsorted(a,(x+neg+1)//neg)).sum()
            cnt-=neg_p[neg_p<=x].size
        if zero.size>0:
            if x>=0:
                cnt+=(a.size-1)*zero.size
        if pos.size>0:
            cnt+=np.searchsorted(a,x//pos,side="right").sum()
            cnt-=pos_p[pos_p<=x].size

        cnt//=2
        if cnt>=k: r=x
        else: l=x

    print(r)

def __starting_point():
    main()
__starting_point()

import numpy as np

n, k = list(map(int, input().split()))
a = np.array(list(map(int, input().split())))
a.sort()

zero = a[a==0]
pos = a[a>0]
neg = a[a<0]

l = -10**18
r = 10**18

# 二分探索
# x以下になる組み合わせがいくつあるか計算する
while l+1<r:
    x = (l + r) // 2
    cnt = 0

    # 0になる組み合わせの個数のカウントを追加
    if x >= 0:
        cnt += n * len(zero)

    cnt += a.searchsorted(x//pos,side='right').sum()
    cnt += (n-a.searchsorted(-(-x//neg),side='left')).sum()
    cnt -= np.count_nonzero(a*a<=x)
    cnt//=2

    if cnt >= k:
        r = x
    else:
        l = x

print(r)