Buggy python submission (verdict: Time Limit Exceeded):
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Nz = bisect.bisect_left(A, 1) - Nn # 0の数
Np = N - Nn - Nz # 正の数の数
An = A[:Nn]
Ap = A[Nn+Nz:]


if Nn*Np >= K: # 答えが負の数
  left = -10**18-1 # False
  right = -1 # True
  n = Nn*Np - K # midより大きくなるのがn個より多いとmid以下のペアがK個以上にならない
  while left+1 < right:
    mid = (left+right) // 2
    i = j = 0
    c = 0
    while i < Nn and j < Np:
      if An[i]*Ap[j] > mid:
        c += 1
        j += 1
        if j >= Np:
          c += (Nn - 1 - i)*Np
      else:
        c += j
        i += 1
      if c > n:
        break
    if c > n:
      left = mid
    else:
      right = mid
  ans = right 
elif Nn*Np + Nz*(Nn+Np) + Nz*(Nz-1)//2 >= K: # 答えが0
  ans = 0
else: # 答えが正
  An = [-an for an in An][::-1]
  N = Nn*(Nn-1)//2 + Np*(Np-1)//2 # 積が正となる組合せ
  k = K - Nn*Np - Nz*(Nn+Np) - Nz*(Nz-1)//2 # 正の数の中でk番目に小さい数が答え
  n = N - k
  left = 0 # False
  right = 10**18 + 1 # True
  while left+1 < right:
    mid = (left+right) // 2
    i = 0
    j = Nn - 1
    c = 0
    while i < j:
      if An[i]*An[j] > mid:
        c += 1
        j -= 1
      else:
        c += Nn - 1 - j
        i += 1
      if i == j:
          c += (Nn-i-1)*(Nn-i-2) // 2
      if c > n:
        break
    
    if c > n:
      left = mid
    else:
      i = 0
      j = Np - 1
      while i < j:
        if Ap[i]*Ap[j] > mid:
          c += 1
          j -= 1
        else:
          c += Np - 1 - j
          i += 1
        if i == j:
            c += (Np-i-1)*(Np-i-2) // 2
        if c > n:
          break
      if c > n:
        left = mid
      else:
        right = mid
  ans = right


print(ans)

Fixed submission:
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Nz = bisect.bisect_left(A, 1) - Nn # 0の数
Np = N - Nn - Nz # 正の数の数
An = A[:Nn]
Ap = A[Nn+Nz:]


if Nn*Np >= K: # 答えが負の数
  left = -10**18-1 # False
  right = -1 # True
  n = Nn*Np - K # midより大きくなるのがn個より多いとmid以下のペアがK個以上にならない
  while left+1 < right:
    mid = (left+right) // 2
    i = j = 0
    c = 0
    while i < Nn and j < Np:
      if An[i]*Ap[j] > mid:
        c += 1
        j += 1
        if j >= Np:
          c += (Nn - 1 - i)*Np
      else:
        c += j
        i += 1
      if c > n:
        break
    if c > n:
      left = mid
    else:
      right = mid
  ans = right 
elif Nn*Np + Nz*(Nn+Np) + Nz*(Nz-1)//2 >= K: # 答えが0
  ans = 0
else: # 答えが正
  An = [-an for an in An][::-1]
  N = Nn*(Nn-1)//2 + Np*(Np-1)//2 # 積が正となる組合せ
  k = K - Nn*Np - Nz*(Nn+Np) - Nz*(Nz-1)//2 # 正の数の中でk番目に小さい数が答え
  n = N - k
  left = 0 # False
  right = 10**18 + 1 # True
  while left+1 < right:
    mid = (left+right) // 2
    i = 0
    j = Nn - 1
    c = 0
    while i < j:
      if An[i]*An[j] > mid:
        c += 1
        j -= 1
      else:
        c += Nn - 1 - j
        i += 1
      if i == j:
          c += (Nn-i-1)*(Nn-i-2) // 2
      if c > n:
        break
    
    if c > n:
      left = mid
    else:
      i = 0
      j = Np - 1
      while i < j:
        if Ap[i]*Ap[j] > mid:
          c += 1
          j -= 1
        else:
          c += Np - 1 - j
          i += 1
        if i == j:
            c += (Np-i-1)*(Np-i-2) // 2
        if c > n:
          break
      if c > n:
        left = mid
      else:
        right = mid
  ans = right


print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Np = N - Nn
An = A[:Nn]
Ap = A[Nn:]
if Nn*Np >= K:  
  left = A[0]*A[-1] - 1
  right = max(A[0]**2, A[-1]**2) + 1
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    res = False
    for an in An:
      idx = bisect.bisect_left(Ap, mid/an)
      c += Np - idx
      if c >= K:
        res = True
        break
    if res:
      right = mid
    else:
      left = mid
  
  ans = -10**20
  for an in An:
    idx = bisect.bisect_left(Ap, right/an)
    if idx < Np:
      ans = max(ans, Ap[idx]*an)
      if ans == right:
        break
else:
  k = K - Nn*Np
  An = [-an for an in An][::-1]
  left = -1
  right = 0
  if An:
    right = An[-1]**2 + 1
  if Ap:
    right = max(right, Ap[-1]**2+1)

  while left+1 < right:
    mid = (left + right)//2
    c = 0
    for i, an in enumerate(An, 1):
      idx = bisect.bisect_right(An, mid/an)
      if idx > i:
        c += idx - i
    
    if c >= k:
      right = mid
    else:
      for i, ap in enumerate(Ap, 1):
        if ap:
          idx = bisect.bisect_right(Ap, mid/ap)
          if idx > i:
            c += idx - i
        else:
          c += Np - i
    
    if c >= k:
      right = mid
    else:
      left = mid
  
  ans = 10**20
  for an in An:
    idx = bisect.bisect_left(An, right/an)
    if idx < Nn:
      ans = min(ans, An[idx]*an)
      if ans == right:
        break
  for ap in Ap:
    if ap:
      idx = bisect.bisect_left(Ap, right/ap)
      if idx < Np:
        ans = min(ans, Ap[idx]*ap)
        if ans == right:
          break
    else:
      if right == 0:
        ans = 0
        break

print(ans)

Fixed submission:
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Nz = bisect.bisect_left(A, 1) - Nn # 0の数
Np = N - Nn - Nz # 正の数の数
An = A[:Nn]
Ap = A[Nn+Nz:]


if Nn*Np >= K: # 答えが負の数
  left = -10**18-1 # False
  right = -1 # True
  n = Nn*Np - K # midより大きくなるのがn個より多いとmid以下のペアがK個以上にならない
  while left+1 < right:
    mid = (left+right) // 2
    i = j = 0
    c = 0
    while i < Nn and j < Np:
      if An[i]*Ap[j] > mid:
        c += 1
        j += 1
        if j >= Np:
          c += (Nn - 1 - i)*Np
      else:
        c += j
        i += 1
      if c > n:
        break
    if c > n:
      left = mid
    else:
      right = mid
  ans = right 
elif Nn*Np + Nz*(Nn+Np) + Nz*(Nz-1)//2 >= K: # 答えが0
  ans = 0
else: # 答えが正
  An = [-an for an in An][::-1]
  N = Nn*(Nn-1)//2 + Np*(Np-1)//2 # 積が正となる組合せ
  k = K - Nn*Np - Nz*(Nn+Np) - Nz*(Nz-1)//2 # 正の数の中でk番目に小さい数が答え
  n = N - k
  left = 0 # False
  right = 10**18 + 1 # True
  while left+1 < right:
    mid = (left+right) // 2
    i = 0
    j = Nn - 1
    c = 0
    while i < j:
      if An[i]*An[j] > mid:
        c += 1
        j -= 1
      else:
        c += Nn - 1 - j
        i += 1
      if i == j:
          c += (Nn-i-1)*(Nn-i-2) // 2
      if c > n:
        break
    
    if c > n:
      left = mid
    else:
      i = 0
      j = Np - 1
      while i < j:
        if Ap[i]*Ap[j] > mid:
          c += 1
          j -= 1
        else:
          c += Np - 1 - j
          i += 1
        if i == j:
            c += (Np-i-1)*(Np-i-2) // 2
        if c > n:
          break
      if c > n:
        left = mid
      else:
        right = mid
  ans = right


print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Np = N - Nn
An = A[:Nn]
Ap = A[Nn:]
if Nn*Np >= K:  
  left = A[0]*A[-1] - 1
  right = max(A[0]**2, A[-1]**2) + 1
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    res = False
    for an in An:
      idx = bisect.bisect_left(Ap, mid/an)
      c += Np - idx
      if c >= K:
        res = True
        break
    if res:
      right = mid
    else:
      left = mid
  
  ans = -10**20
  for an in An:
    idx = bisect.bisect_left(Ap, right/an)
    if idx < Np:
      ans = max(ans, Ap[idx]*an)
      if ans == right:
        break
else:
  k = K - Nn*Np
  An = [-an for an in An][::-1]
  left = -1
  right = 10**20
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    for i, an in enumerate(An, 1):
      idx = bisect.bisect_right(An, mid/an)
      if idx > i:
        c += idx - i
    
    if c >= k:
      right = mid
    else:
      for i, ap in enumerate(Ap, 1):
        if ap:
          idx = bisect.bisect_right(Ap, mid/ap)
          if idx > i:
            c += idx - i
        else:
          c += Np - i
    
    if c >= k:
      right = mid
    else:
      left = mid
  
  ans = 10**20
  for an in An:
    idx = bisect.bisect_left(An, right/an)
    if idx < Nn:
      ans = min(ans, An[idx]*an)
      if ans == right:
        break
  for ap in Ap:
    if ap:
      idx = bisect.bisect_left(Ap, right/ap)
      if idx < Np:
        ans = min(ans, Ap[idx]*ap)
        if ans == right:
          break
    else:
      if right == 0:
        ans = 0
        break

print(ans)

Fixed submission:
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Nz = bisect.bisect_left(A, 1) - Nn # 0の数
Np = N - Nn - Nz # 正の数の数
An = A[:Nn]
Ap = A[Nn+Nz:]


if Nn*Np >= K: # 答えが負の数
  left = -10**18-1 # False
  right = -1 # True
  n = Nn*Np - K # midより大きくなるのがn個より多いとmid以下のペアがK個以上にならない
  while left+1 < right:
    mid = (left+right) // 2
    i = j = 0
    c = 0
    while i < Nn and j < Np:
      if An[i]*Ap[j] > mid:
        c += 1
        j += 1
        if j >= Np:
          c += (Nn - 1 - i)*Np
      else:
        c += j
        i += 1
      if c > n:
        break
    if c > n:
      left = mid
    else:
      right = mid
  ans = right 
elif Nn*Np + Nz*(Nn+Np) + Nz*(Nz-1)//2 >= K: # 答えが0
  ans = 0
else: # 答えが正
  An = [-an for an in An][::-1]
  N = Nn*(Nn-1)//2 + Np*(Np-1)//2 # 積が正となる組合せ
  k = K - Nn*Np - Nz*(Nn+Np) - Nz*(Nz-1)//2 # 正の数の中でk番目に小さい数が答え
  n = N - k
  left = 0 # False
  right = 10**18 + 1 # True
  while left+1 < right:
    mid = (left+right) // 2
    i = 0
    j = Nn - 1
    c = 0
    while i < j:
      if An[i]*An[j] > mid:
        c += 1
        j -= 1
      else:
        c += Nn - 1 - j
        i += 1
      if i == j:
          c += (Nn-i-1)*(Nn-i-2) // 2
      if c > n:
        break
    
    if c > n:
      left = mid
    else:
      i = 0
      j = Np - 1
      while i < j:
        if Ap[i]*Ap[j] > mid:
          c += 1
          j -= 1
        else:
          c += Np - 1 - j
          i += 1
        if i == j:
            c += (Np-i-1)*(Np-i-2) // 2
        if c > n:
          break
      if c > n:
        left = mid
      else:
        right = mid
  ans = right


print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Np = N - Nn
An = A[:Nn]
Ap = A[Nn:]
if Nn*Np >= K:  
  left = A[0]*A[-1] - 1
  right = max(A[0]**2, A[-1]**2) + 1
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    res = False
    for an in An:
      idx = bisect.bisect_left(Ap, mid/an)
      c += Np - idx
      if c >= K:
        res = True
        break
    if res:
      right = mid
    else:
      left = mid
  
  ans = -10**20
  for an in An:
    idx = bisect.bisect_left(Ap, right/an)
    if idx < Np:
      ans = max(ans, Ap[idx]*an)    
else:
  k = K - Nn*Np
  An = [-an for an in An][::-1]
  left = -1
  right = 10**20
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    for i, an in enumerate(An, 1):
      idx = bisect.bisect_right(An, mid/an)
      if idx > i:
        c += idx - i
    
    for i, ap in enumerate(Ap, 1):
      if ap:
        idx = bisect.bisect_right(Ap, mid/ap)
        if idx > i:
          c += idx - i
      else:
        c += Np - i
    
    if c >= k:
      right = mid
    else:
      left = mid
  
  ans = 10**20
  for an in An:
    idx = bisect.bisect_left(An, right/an)
    if idx < Nn:
      ans = min(ans, An[idx]*an)
  for ap in Ap:
    if ap:
      idx = bisect.bisect_left(Ap, right/ap)
      if idx < Np:
        ans = min(ans, Ap[idx]*ap)
    else:
      if right == 0:
        ans = 0
        break

print(ans)

Fixed submission:
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Nz = bisect.bisect_left(A, 1) - Nn # 0の数
Np = N - Nn - Nz # 正の数の数
An = A[:Nn]
Ap = A[Nn+Nz:]


if Nn*Np >= K: # 答えが負の数
  left = -10**18-1 # False
  right = -1 # True
  n = Nn*Np - K # midより大きくなるのがn個より多いとmid以下のペアがK個以上にならない
  while left+1 < right:
    mid = (left+right) // 2
    i = j = 0
    c = 0
    while i < Nn and j < Np:
      if An[i]*Ap[j] > mid:
        c += 1
        j += 1
        if j >= Np:
          c += (Nn - 1 - i)*Np
      else:
        c += j
        i += 1
      if c > n:
        break
    if c > n:
      left = mid
    else:
      right = mid
  ans = right 
elif Nn*Np + Nz*(Nn+Np) + Nz*(Nz-1)//2 >= K: # 答えが0
  ans = 0
else: # 答えが正
  An = [-an for an in An][::-1]
  N = Nn*(Nn-1)//2 + Np*(Np-1)//2 # 積が正となる組合せ
  k = K - Nn*Np - Nz*(Nn+Np) - Nz*(Nz-1)//2 # 正の数の中でk番目に小さい数が答え
  n = N - k
  left = 0 # False
  right = 10**18 + 1 # True
  while left+1 < right:
    mid = (left+right) // 2
    i = 0
    j = Nn - 1
    c = 0
    while i < j:
      if An[i]*An[j] > mid:
        c += 1
        j -= 1
      else:
        c += Nn - 1 - j
        i += 1
      if i == j:
          c += (Nn-i-1)*(Nn-i-2) // 2
      if c > n:
        break
    
    if c > n:
      left = mid
    else:
      i = 0
      j = Np - 1
      while i < j:
        if Ap[i]*Ap[j] > mid:
          c += 1
          j -= 1
        else:
          c += Np - 1 - j
          i += 1
        if i == j:
            c += (Np-i-1)*(Np-i-2) // 2
        if c > n:
          break
      if c > n:
        left = mid
      else:
        right = mid
  ans = right


print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Np = N - Nn
An = A[:Nn]
Ap = A[Nn:]
if Nn*Np >= K:  
  left = A[0]*A[-1] - 1
  right = max(A[0]**2, A[-1]**2) + 1
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    res = False
    for an in An:
      idx = bisect.bisect_left(Ap, mid/an)
      c += Np - idx
      if c >= K:
        res = True
        break
    if res:
      right = mid
    else:
      left = mid
  
  ans = -10**20
  for an in An:
    idx = bisect.bisect_left(Ap, right/an)
    if idx < Np:
      ans = max(ans, Ap[idx]*an)    
else:
  k = K - Nn*Np
  An = [-an for an in An][::-1]
  left = -1
  right = 10**20
  while left+1 < right:
    mid = (left + right)//2
    c = 0
    for i, an in enumerate(An, 1):
      idx = bisect.bisect_right(An, mid/an)
      if idx > i:
        c += idx - i
    
    for i, ap in enumerate(Ap, 1):
      if ap:
        idx = bisect.bisect_right(Ap, mid/ap)
        if idx > i:
          c += idx - i
      else:
        c += Np - i
    
    if c >= k:
      right = mid
    else:
      left = mid
  
  ans = 10**20
  for an in An:
    idx = bisect.bisect_left(An, right/an)
    if idx < Nn:
      ans = min(ans, An[idx]*an)
  for ap in Ap:
    if ap:
      idx = bisect.bisect_left(Ap, right/ap)
      if idx < Np:
        ans = min(ans, Ap[idx]*ap)
    else:
      if right == 0:
        ans = 0
        break

print(ans)

Fixed submission:
import bisect

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

A.sort()
Nn = bisect.bisect_left(A, 0) # 負の数の数
Nz = bisect.bisect_left(A, 1) - Nn # 0の数
Np = N - Nn - Nz # 正の数の数
An = A[:Nn]
Ap = A[Nn+Nz:]


if Nn*Np >= K: # 答えが負の数
  left = -10**18-1 # False
  right = -1 # True
  n = Nn*Np - K # midより大きくなるのがn個より多いとmid以下のペアがK個以上にならない
  while left+1 < right:
    mid = (left+right) // 2
    i = j = 0
    c = 0
    while i < Nn and j < Np:
      if An[i]*Ap[j] > mid:
        c += 1
        j += 1
        if j >= Np:
          c += (Nn - 1 - i)*Np
      else:
        c += j
        i += 1
      if c > n:
        break
    if c > n:
      left = mid
    else:
      right = mid
  ans = right 
elif Nn*Np + Nz*(Nn+Np) + Nz*(Nz-1)//2 >= K: # 答えが0
  ans = 0
else: # 答えが正
  An = [-an for an in An][::-1]
  N = Nn*(Nn-1)//2 + Np*(Np-1)//2 # 積が正となる組合せ
  k = K - Nn*Np - Nz*(Nn+Np) - Nz*(Nz-1)//2 # 正の数の中でk番目に小さい数が答え
  n = N - k
  left = 0 # False
  right = 10**18 + 1 # True
  while left+1 < right:
    mid = (left+right) // 2
    i = 0
    j = Nn - 1
    c = 0
    while i < j:
      if An[i]*An[j] > mid:
        c += 1
        j -= 1
      else:
        c += Nn - 1 - j
        i += 1
      if i == j:
          c += (Nn-i-1)*(Nn-i-2) // 2
      if c > n:
        break
    
    if c > n:
      left = mid
    else:
      i = 0
      j = Np - 1
      while i < j:
        if Ap[i]*Ap[j] > mid:
          c += 1
          j -= 1
        else:
          c += Np - 1 - j
          i += 1
        if i == j:
            c += (Np-i-1)*(Np-i-2) // 2
        if c > n:
          break
      if c > n:
        left = mid
      else:
        right = mid
  ans = right


print(ans)