Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left, bisect_right
N, K = map(int, input().split())
A = sorted(list(map(int, input().split())))
 
negative_end = bisect_left(A, 0)
positive_start = bisect_right(A, 0)
 
positive_cnt = N - positive_start
negative_cnt = negative_end
zero_cnt = N - (positive_cnt + negative_cnt)
 
negative_pairs_cnt = positive_cnt * negative_cnt
zero_pairs_cnt = zero_cnt * (positive_cnt + negative_cnt) + (zero_cnt * (zero_cnt - 1) // 2)


# 答えが負の場合
if K <= negative_pairs_cnt:
    # にぶたん: X以下になるペアがK個以上あるか？
    ok, ng = 0, -10 ** 18
    while abs(ok - ng) > 1:
        X = (ok + ng) // 2
        or_higher_cnt, r = 0, positive_start
        for l in range(negative_end):
            while (r < N) and (A[l] * A[r] > X):
                r += 1
            or_higher_cnt += positive_cnt - (r - positive_start)
 
        if or_higher_cnt >= K:
            ok = X
        else:
            ng = X
 
    print(ok)

# 答えが0の場合
elif K <= negative_pairs_cnt + zero_pairs_cnt:
    print(0)
# 答えが正の場合
else:
    # にぶたん: X以下になるペアがK個以上あるか？
    K -= (negative_pairs_cnt + zero_pairs_cnt)
    ok, ng = 10 ** 18, 0
    while abs(ok - ng) > 1:
        X = (ok + ng) // 2
        or_higher_cnt = 0
 
        r = N - 1
        for l in range(positive_start, N):
            while (r < N) and (A[l] * A[r] > X) and (l < r):
                r -= 1
            or_higher_cnt += max(0, r - l)
 
        l = 0
        for r in range(negative_end - 1, -1, -1):
            while (l < N) and (A[l] * A[r] > X) and (l < r):
                l += 1
 
            or_higher_cnt += max(0, r - l)
 
        if or_higher_cnt >= K:
            ok = X
        else:
            ng = X
 
    print(ok)

Fixed submission:
'''たのん「決め打ち2分探索」
各ペアの積を順番に並べたときのK番目の値を愚直に計算すると、
積の計算にO(N^2)、それらの値をソートするのにO(N^2logN)かかってしまう。
そこで考え方を変え、勝手に決めた値XがK番目の値になるかどうかを
判定することを考えてみます。
勝手に決めた値Xよりも積が小さくなるペアの個数を数え、
それがK個以上であればK番目の値はXより小さく、
K個未満であればK番目の値はXより大きいことが分かります。
1回の判定にかかる計算量は、2数の積の片方を決めたとき
もう片方として取ってこられる個数をしゃくとり法によって求めると
トータルO(N)、2分探索によって求めると1要素あたりの計算量がO(logN)なので
トータルO(NlogN)となります。
また判定を行う回数は、制約より0<=|Ai|<=10^9なので、
初期値として0と10^18+1を与えれば十分で、
判定の回数は高々log(10^18)回程度だと分かります。
今回の制約は-10^9<=Ai<=10^9より、
小さい方からK番目の要素の値が負になるか、それとも0になるか、
それとも正になるかで場合分けをして考える必要があります。
まずK番目の要素の値が負になる場合、2数の積の組み合わせとしては、
(負の数)x(正の数)のみがあり得ます。
このときは、負の数からある要素を取ってきたときもう片方として
正の数から取ってこられる個数を求めればよいです。
ただし以下の実装では負数のマイナスを取って計算しているため
2数の積の大小が逆転し、(負の数)x(正の数)の小さいほうからK番目の数は、
(負の数の絶対値)x(正の数)の小さいほうから
(負の数の個数-K)番目の数(=大きいほうからK番目の数)に相当します。
次にK番目の要素の値が正になる場合、2数の積の組み合わせとしては、
(負の数)x(負の数)と(正の数)x(正の数)の2つがあり得ます。
このときは、負の数からある要素を取ってきたとき
もう片方として負の数から取ってこられる個数と、
正の数からある要素を取ってきたとき、もう片方として正の数から
取ってこられる個数をそれぞれ求めて足し合わせればよいです。
ただし、同じ要素を2回選ぶ場合が含まれてしまっていることと、
そして各ペアが2回数えられることに注意し、個数を修正する必要があります。
'''

n,k=map(int,input().split())
arr=list(map(int,input().split()))
arr=sorted(arr)
nc=0
zc=0
pc=0
for i in range(n): #負数の数(nc)、0の数(zc)、正数の数(pc)を数える
 if arr[i]<0:
   nc+=1
 elif arr[i]==0:
   zc+=1
 else:
   pc+=1
ncc=nc*pc #積が負となるペアの個数を求める
zcc=zc*(nc+pc)+(zc*(zc-1))//2 #積が0となるペアの個数を求める
pcc=(nc*(nc-1))//2+(pc*(pc-1))//2 #積が正となるペアの個数を求める
if k<=ncc: #K番目の値が負の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k=ncc-k #負数のマイナスを取って計算しているため積の大小が逆転するので、大きなほうからK番目、すなわち、小さなほうから(積が負となるペアの個数-K)番目の値を求める
 while r-l!=1:
   mid=(l+r)//2
   cnt=0
   pos=c2-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     while pos!=-1:
       if arr2[pos]>mid//arr1[i]:
         pos-=1
       else:
         break        
     cnt+=pos+1
   if cnt>k: #勝手に決めた値mid以下の個数が(積が負となるペアの個数-K)個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(-r) #負数のマイナスを取って計算したので最後にマイナスを付けて出力する
elif k<=(ncc+zcc): #K番目の値が0の場合
 print(0)
else: #K番目の値が正の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k-=(ncc+zcc) #正数の中で小さい順にK番目の数を調べたいので負数、0の数を取り除く
 while r-l!=1:
   mid=(l+r)//2
   cnt1=0
   pos1=c1-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる負数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos1!=-1:
       if arr1[pos1]>mid//arr1[i]:
         pos1-=1
       else:
         break
     tmp+=pos1+1
     if arr1[i]**2<mid: #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
       tmp-=1
     cnt1+=tmp
   cnt1=cnt1//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt2=0
   pos2=c2-1
   for i in range(c2): #各正数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos2!=-1:
       if arr2[pos2]>mid//arr2[i]:
         pos2-=1
       else:
         break
     tmp+=pos2+1
     if arr2[i]**2<mid:
       tmp-=1 #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
     cnt2+=tmp
   cnt2=cnt2//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt=cnt1+cnt2
   if cnt>=k: #勝手に決めた値mid以下の個数がK個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(r)

Buggy python submission (verdict: Time Limit Exceeded):
'''たのん「決め打ち2分探索」
各ペアの積を順番に並べたときのK番目の値を愚直に計算すると、
積の計算にO(N^2)、それらの値をソートするのにO(N^2logN)かかってしまう。
そこで考え方を変え、勝手に決めた値XがK番目の値になるかどうかを
判定することを考えてみます。
勝手に決めた値Xよりも積が小さくなるペアの個数を数え、
それがK個以上であればK番目の値はXより小さく、
K個未満であればK番目の値はXより大きいことが分かります。
1回の判定にかかる計算量は、2数の積の片方を決めたとき
もう片方として取ってこられる個数をしゃくとり法によって求めると
トータルO(N)、2分探索によって求めると1要素あたりの計算量がO(logN)なので
トータルO(NlogN)となります。
また判定を行う回数は、制約より0<=|Ai|<=10^9なので、
初期値として0と10^18+1を与えれば十分で、
判定の回数は高々log(10^18)回程度だと分かります。
今回の制約は-10^9<=Ai<=10^9より、
小さい方からK番目の要素の値が負になるか、それとも0になるか、
それとも正になるかで場合分けをして考える必要があります。
まずK番目の要素の値が負になる場合、2数の積の組み合わせとしては、
(負の数)x(正の数)のみがあり得ます。
このときは、負の数からある要素を取ってきたときもう片方として
正の数から取ってこられる個数を求めればよいです。
ただし以下の実装では負数のマイナスを取って計算しているため
2数の積の大小が逆転し、(負の数)x(正の数)の小さいほうからK番目の数は、
(負の数の絶対値)x(正の数)の小さいほうから
(負の数の個数-K)番目の数(=大きいほうからK番目の数)に相当します。
次にK番目の要素の値が正になる場合、2数の積の組み合わせとしては、
(負の数)x(負の数)と(正の数)x(正の数)の2つがあり得ます。
このときは、負の数からある要素を取ってきたとき
もう片方として負の数から取ってこられる個数と、
正の数からある要素を取ってきたとき、もう片方として正の数から
取ってこられる個数をそれぞれ求めて足し合わせればよいです。
ただし、同じ要素を2回選ぶ場合が含まれてしまっていることと、
そして各ペアが2回数えられることに注意し、個数を修正する必要があります。
'''

n,k=map(int,input().split())
arr=list(map(int,input().split()))
arr=sorted(arr)
nc=0
zc=0
pc=0
for i in range(n): #負数の数(nc)、0の数(zc)、正数の数(pc)を数える
 if arr[i]<0:
   nc+=1
 elif arr[i]==0:
   zc+=1
 else:
   pc+=1
ncc=nc*pc #積が負となるペアの個数を求める
zcc=zc*(nc+pc)+(zc*(zc-1))//2 #積が0となるペアの個数を求める
pcc=(nc*(nc-1))//2+(pc*(pc-1))//2 #積が正となるペアの個数を求める
if k<=ncc: #K番目の値が負の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k=ncc-k #負数のマイナスを取って計算しているため積の大小が逆転するので、大きなほうからK番目、すなわち、小さなほうから(積が負となるペアの個数-K)番目の値を求める
 while r-l!=1:
   mid=(l+r)//2
   cnt=0
   pos=c2-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     while pos!=-1:
       if arr2[pos]>mid//arr1[i]:
         pos-=1
       else:
         break        
     cnt+=pos+1
   if cnt>k: #勝手に決めた値mid以下の個数が(積が負となるペアの個数-K)個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(-r) #負数のマイナスを取って計算したので最後にマイナスを付けて出力する
elif k<=(ncc+zcc): #K番目の値が0の場合
 print(0)
else: #K番目の値が正の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k-=(ncc+zcc) #正数の中で小さい順にK番目の数を調べたいので負数、0の数を取り除く
 while r-l!=1:
   mid=(l+r)//2
   cnt1=0
   pos1=c1-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる負数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos1!=-1:
       if arr1[pos1]>mid//arr1[i]:
         pos1-=1
       else:
         break
     tmp+=pos1+1
     if arr1[i]**2<mid: #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
       tmp-=1
     cnt1+=tmp
   cnt1=cnt1//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt2=0
   pos2=c2-1
   for i in range(c2): #各正数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos2!=-1:
       if arr2[pos2]>mid//arr2[i]:
         pos2-=1
       else:
         break
     tmp+=pos2+1
     if arr2[i]**2<mid:
       tmp-=1 #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
     cnt2+=tmp
   cnt2=cnt2//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt=cnt1+cnt2
   if cnt>=k: #勝手に決めた値mid以下の個数がK個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(r)

Fixed submission:
'''たのん「決め打ち2分探索」
各ペアの積を順番に並べたときのK番目の値を愚直に計算すると、
積の計算にO(N^2)、それらの値をソートするのにO(N^2logN)かかってしまう。
そこで考え方を変え、勝手に決めた値XがK番目の値になるかどうかを
判定することを考えてみます。
勝手に決めた値Xよりも積が小さくなるペアの個数を数え、
それがK個以上であればK番目の値はXより小さく、
K個未満であればK番目の値はXより大きいことが分かります。
1回の判定にかかる計算量は、2数の積の片方を決めたとき
もう片方として取ってこられる個数をしゃくとり法によって求めると
トータルO(N)、2分探索によって求めると1要素あたりの計算量がO(logN)なので
トータルO(NlogN)となります。
また判定を行う回数は、制約より0<=|Ai|<=10^9なので、
初期値として0と10^18+1を与えれば十分で、
判定の回数は高々log(10^18)回程度だと分かります。
今回の制約は-10^9<=Ai<=10^9より、
小さい方からK番目の要素の値が負になるか、それとも0になるか、
それとも正になるかで場合分けをして考える必要があります。
まずK番目の要素の値が負になる場合、2数の積の組み合わせとしては、
(負の数)x(正の数)のみがあり得ます。
このときは、負の数からある要素を取ってきたときもう片方として
正の数から取ってこられる個数を求めればよいです。
ただし以下の実装では負数のマイナスを取って計算しているため
2数の積の大小が逆転し、(負の数)x(正の数)の小さいほうからK番目の数は、
(負の数の絶対値)x(正の数)の小さいほうから
(負の数の個数-K)番目の数(=大きいほうからK番目の数)に相当します。
次にK番目の要素の値が正になる場合、2数の積の組み合わせとしては、
(負の数)x(負の数)と(正の数)x(正の数)の2つがあり得ます。
このときは、負の数からある要素を取ってきたとき
もう片方として負の数から取ってこられる個数と、
正の数からある要素を取ってきたとき、もう片方として正の数から
取ってこられる個数をそれぞれ求めて足し合わせればよいです。
ただし、同じ要素を2回選ぶ場合が含まれてしまっていることと、
そして各ペアが2回数えられることに注意し、個数を修正する必要があります。
'''

n,k=map(int,input().split())
arr=list(map(int,input().split()))
arr=sorted(arr)
nc=0
zc=0
pc=0
for i in range(n): #負数の数(nc)、0の数(zc)、正数の数(pc)を数える
 if arr[i]<0:
   nc+=1
 elif arr[i]==0:
   zc+=1
 else:
   pc+=1
ncc=nc*pc #積が負となるペアの個数を求める
zcc=zc*(nc+pc)+(zc*(zc-1))//2 #積が0となるペアの個数を求める
pcc=(nc*(nc-1))//2+(pc*(pc-1))//2 #積が正となるペアの個数を求める
if k<=ncc: #K番目の値が負の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k=ncc-k #負数のマイナスを取って計算しているため積の大小が逆転するので、大きなほうからK番目、すなわち、小さなほうから(積が負となるペアの個数-K)番目の値を求める
 while r-l!=1:
   mid=(l+r)//2
   cnt=0
   pos=c2-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     while pos!=-1:
       if arr2[pos]>mid//arr1[i]:
         pos-=1
       else:
         break        
     cnt+=pos+1
   if cnt>k: #勝手に決めた値mid以下の個数が(積が負となるペアの個数-K)個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(-r) #負数のマイナスを取って計算したので最後にマイナスを付けて出力する
elif k<=(ncc+zcc): #K番目の値が0の場合
 print(0)
else: #K番目の値が正の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k-=(ncc+zcc) #正数の中で小さい順にK番目の数を調べたいので負数、0の数を取り除く
 while r-l!=1:
   mid=(l+r)//2
   cnt1=0
   pos1=c1-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる負数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos1!=-1:
       if arr1[pos1]>mid//arr1[i]:
         pos1-=1
       else:
         break
     tmp+=pos1+1
     if arr1[i]**2<mid: #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
       tmp-=1
     cnt1+=tmp
   cnt1=cnt1//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt2=0
   pos2=c2-1
   for i in range(c2): #各正数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos2!=-1:
       if arr2[pos2]>mid//arr2[i]:
         pos2-=1
       else:
         break
     tmp+=pos2+1
     if arr2[i]**2<mid:
       tmp-=1 #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
     cnt2+=tmp
   cnt2=cnt2//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt=cnt1+cnt2
   if cnt>=k: #勝手に決めた値mid以下の個数がK個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(r)

Buggy python submission (verdict: Time Limit Exceeded):
import itertools
A,B=map(int,input().split())
L=list(map(int,input().split()))
c = itertools.combinations(L, 2)
ans=[]
for i in c:
  ans.append(i[0]*i[1])
ans.sort()
print(ans[B-1])

Fixed submission:
'''たのん「決め打ち2分探索」
各ペアの積を順番に並べたときのK番目の値を愚直に計算すると、
積の計算にO(N^2)、それらの値をソートするのにO(N^2logN)かかってしまう。
そこで考え方を変え、勝手に決めた値XがK番目の値になるかどうかを
判定することを考えてみます。
勝手に決めた値Xよりも積が小さくなるペアの個数を数え、
それがK個以上であればK番目の値はXより小さく、
K個未満であればK番目の値はXより大きいことが分かります。
1回の判定にかかる計算量は、2数の積の片方を決めたとき
もう片方として取ってこられる個数をしゃくとり法によって求めると
トータルO(N)、2分探索によって求めると1要素あたりの計算量がO(logN)なので
トータルO(NlogN)となります。
また判定を行う回数は、制約より0<=|Ai|<=10^9なので、
初期値として0と10^18+1を与えれば十分で、
判定の回数は高々log(10^18)回程度だと分かります。
今回の制約は-10^9<=Ai<=10^9より、
小さい方からK番目の要素の値が負になるか、それとも0になるか、
それとも正になるかで場合分けをして考える必要があります。
まずK番目の要素の値が負になる場合、2数の積の組み合わせとしては、
(負の数)x(正の数)のみがあり得ます。
このときは、負の数からある要素を取ってきたときもう片方として
正の数から取ってこられる個数を求めればよいです。
ただし以下の実装では負数のマイナスを取って計算しているため
2数の積の大小が逆転し、(負の数)x(正の数)の小さいほうからK番目の数は、
(負の数の絶対値)x(正の数)の小さいほうから
(負の数の個数-K)番目の数(=大きいほうからK番目の数)に相当します。
次にK番目の要素の値が正になる場合、2数の積の組み合わせとしては、
(負の数)x(負の数)と(正の数)x(正の数)の2つがあり得ます。
このときは、負の数からある要素を取ってきたとき
もう片方として負の数から取ってこられる個数と、
正の数からある要素を取ってきたとき、もう片方として正の数から
取ってこられる個数をそれぞれ求めて足し合わせればよいです。
ただし、同じ要素を2回選ぶ場合が含まれてしまっていることと、
そして各ペアが2回数えられることに注意し、個数を修正する必要があります。
'''

n,k=map(int,input().split())
arr=list(map(int,input().split()))
arr=sorted(arr)
nc=0
zc=0
pc=0
for i in range(n): #負数の数(nc)、0の数(zc)、正数の数(pc)を数える
 if arr[i]<0:
   nc+=1
 elif arr[i]==0:
   zc+=1
 else:
   pc+=1
ncc=nc*pc #積が負となるペアの個数を求める
zcc=zc*(nc+pc)+(zc*(zc-1))//2 #積が0となるペアの個数を求める
pcc=(nc*(nc-1))//2+(pc*(pc-1))//2 #積が正となるペアの個数を求める
if k<=ncc: #K番目の値が負の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k=ncc-k #負数のマイナスを取って計算しているため積の大小が逆転するので、大きなほうからK番目、すなわち、小さなほうから(積が負となるペアの個数-K)番目の値を求める
 while r-l!=1:
   mid=(l+r)//2
   cnt=0
   pos=c2-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     while pos!=-1:
       if arr2[pos]>mid//arr1[i]:
         pos-=1
       else:
         break        
     cnt+=pos+1
   if cnt>k: #勝手に決めた値mid以下の個数が(積が負となるペアの個数-K)個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(-r) #負数のマイナスを取って計算したので最後にマイナスを付けて出力する
elif k<=(ncc+zcc): #K番目の値が0の場合
 print(0)
else: #K番目の値が正の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k-=(ncc+zcc) #正数の中で小さい順にK番目の数を調べたいので負数、0の数を取り除く
 while r-l!=1:
   mid=(l+r)//2
   cnt1=0
   pos1=c1-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる負数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos1!=-1:
       if arr1[pos1]>mid//arr1[i]:
         pos1-=1
       else:
         break
     tmp+=pos1+1
     if arr1[i]**2<mid: #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
       tmp-=1
     cnt1+=tmp
   cnt1=cnt1//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt2=0
   pos2=c2-1
   for i in range(c2): #各正数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos2!=-1:
       if arr2[pos2]>mid//arr2[i]:
         pos2-=1
       else:
         break
     tmp+=pos2+1
     if arr2[i]**2<mid:
       tmp-=1 #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
     cnt2+=tmp
   cnt2=cnt2//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt=cnt1+cnt2
   if cnt>=k: #勝手に決めた値mid以下の個数がK個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(r)

Buggy python submission (verdict: Time Limit Exceeded):
import itertools
A,B=map(int,input().split())
L=list(map(int,input().split()))
c = itertools.combinations(L, 2)
ans=[]
for i in c:
  ans.append(i[0]*i[1])
ans.sort()
print(ans[B-1])

Fixed submission:
'''たのん「決め打ち2分探索」
各ペアの積を順番に並べたときのK番目の値を愚直に計算すると、
積の計算にO(N^2)、それらの値をソートするのにO(N^2logN)かかってしまう。
そこで考え方を変え、勝手に決めた値XがK番目の値になるかどうかを
判定することを考えてみます。
勝手に決めた値Xよりも積が小さくなるペアの個数を数え、
それがK個以上であればK番目の値はXより小さく、
K個未満であればK番目の値はXより大きいことが分かります。
1回の判定にかかる計算量は、2数の積の片方を決めたとき
もう片方として取ってこられる個数をしゃくとり法によって求めると
トータルO(N)、2分探索によって求めると1要素あたりの計算量がO(logN)なので
トータルO(NlogN)となります。
また判定を行う回数は、制約より0<=|Ai|<=10^9なので、
初期値として0と10^18+1を与えれば十分で、
判定の回数は高々log(10^18)回程度だと分かります。
今回の制約は-10^9<=Ai<=10^9より、
小さい方からK番目の要素の値が負になるか、それとも0になるか、
それとも正になるかで場合分けをして考える必要があります。
まずK番目の要素の値が負になる場合、2数の積の組み合わせとしては、
(負の数)x(正の数)のみがあり得ます。
このときは、負の数からある要素を取ってきたときもう片方として
正の数から取ってこられる個数を求めればよいです。
ただし以下の実装では負数のマイナスを取って計算しているため
2数の積の大小が逆転し、(負の数)x(正の数)の小さいほうからK番目の数は、
(負の数の絶対値)x(正の数)の小さいほうから
(負の数の個数-K)番目の数(=大きいほうからK番目の数)に相当します。
次にK番目の要素の値が正になる場合、2数の積の組み合わせとしては、
(負の数)x(負の数)と(正の数)x(正の数)の2つがあり得ます。
このときは、負の数からある要素を取ってきたとき
もう片方として負の数から取ってこられる個数と、
正の数からある要素を取ってきたとき、もう片方として正の数から
取ってこられる個数をそれぞれ求めて足し合わせればよいです。
ただし、同じ要素を2回選ぶ場合が含まれてしまっていることと、
そして各ペアが2回数えられることに注意し、個数を修正する必要があります。
'''

n,k=map(int,input().split())
arr=list(map(int,input().split()))
arr=sorted(arr)
nc=0
zc=0
pc=0
for i in range(n): #負数の数(nc)、0の数(zc)、正数の数(pc)を数える
 if arr[i]<0:
   nc+=1
 elif arr[i]==0:
   zc+=1
 else:
   pc+=1
ncc=nc*pc #積が負となるペアの個数を求める
zcc=zc*(nc+pc)+(zc*(zc-1))//2 #積が0となるペアの個数を求める
pcc=(nc*(nc-1))//2+(pc*(pc-1))//2 #積が正となるペアの個数を求める
if k<=ncc: #K番目の値が負の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k=ncc-k #負数のマイナスを取って計算しているため積の大小が逆転するので、大きなほうからK番目、すなわち、小さなほうから(積が負となるペアの個数-K)番目の値を求める
 while r-l!=1:
   mid=(l+r)//2
   cnt=0
   pos=c2-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     while pos!=-1:
       if arr2[pos]>mid//arr1[i]:
         pos-=1
       else:
         break        
     cnt+=pos+1
   if cnt>k: #勝手に決めた値mid以下の個数が(積が負となるペアの個数-K)個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(-r) #負数のマイナスを取って計算したので最後にマイナスを付けて出力する
elif k<=(ncc+zcc): #K番目の値が0の場合
 print(0)
else: #K番目の値が正の場合
 arr1=[]
 arr2=[]
 for i in range(n): #負数、正数をそれぞれ昇順に並べる
   if arr[i]<0:
     arr1.append(-arr[i])
   elif arr[i]>0:
     arr2.append(arr[i])
 arr1=arr1[::-1]
 c1=len(arr1)
 c2=len(arr2)
 l=0
 r=10**18+1
 k-=(ncc+zcc) #正数の中で小さい順にK番目の数を調べたいので負数、0の数を取り除く
 while r-l!=1:
   mid=(l+r)//2
   cnt1=0
   pos1=c1-1
   for i in range(c1): #各負数ごとに積が勝手に決めた値midよりも小さくなる負数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos1!=-1:
       if arr1[pos1]>mid//arr1[i]:
         pos1-=1
       else:
         break
     tmp+=pos1+1
     if arr1[i]**2<mid: #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
       tmp-=1
     cnt1+=tmp
   cnt1=cnt1//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt2=0
   pos2=c2-1
   for i in range(c2): #各正数ごとに積が勝手に決めた値midよりも小さくなる正数の個数を求め足し合わせる(しゃくとり法)
     tmp=0
     while pos2!=-1:
       if arr2[pos2]>mid//arr2[i]:
         pos2-=1
       else:
         break
     tmp+=pos2+1
     if arr2[i]**2<mid:
       tmp-=1 #各要素について、自身を2回選んだ場合の積が勝手に決めた値mid以下なら条件を満たすペアの個数を1減らす
     cnt2+=tmp
   cnt2=cnt2//2 #上記の処理では同じペアが2回数えられているので個数を半分にする
   cnt=cnt1+cnt2
   if cnt>=k: #勝手に決めた値mid以下の個数がK個以上であれば真の値はmid以下
     r=mid
   else: #そうでなければ真の値はmid以上
     l=mid
 print(r)