Buggy python submission (verdict: Time Limit Exceeded):
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():
    from bisect import bisect_left, bisect_right

    INF = 10 ** 18 + 1

    def count(x):
        # a*b<=x
        # a>=0
        #   b<=x//a
        # a<0
        #   (-a)*b>=(-x)
        #   (-a)*b<(-x)
        #   (-a)*b<=(-x-1)
        #   b<=(-x-1)//(-a)

        cnt = 0
        for i in range(n):
            # A[i] < 0
            key = (-x - 1) // (-A[i])
            cnt += N - bisect_right(A, key)
            if A[i] * A[i] <= x:
                cnt -= 1

        if x >= 0:
            cnt += (z - n) * (N - 1)

        for i in range(z, N):
            # A[i] > 0
            key = x // A[i]
            cnt += bisect_right(A, key)
            if A[i] * A[i] <= x:
                cnt -= 1

        return cnt // 2

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

    n = bisect_left(a=A, x=0)  # [0,n)=>負
    z = bisect_left(a=A, x=1)  # [n,z)=>0

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

    print(ans)


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
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():
    from bisect import bisect_left, bisect_right

    INF = 10 ** 18 + 1

    def count(x):
        # a*b<=x
        # a>=0
        #   b<=x//a
        # a<0
        #   (-a)*b>=(-x)
        #   (-a)*b<(-x)
        #   (-a)*b<=(-x-1)
        #   b<=(-x-1)//(-a)

        cnt = 0
        for i in range(n):
            # A[i] < 0
            key = (-x - 1) // (-A[i])
            cnt += N - bisect_right(A, key)
            if A[i] * A[i] <= x:
                cnt -= 1

        if x >= 0:
            cnt += (z - n) * (N - 1)

        for i in range(z, N):
            # A[i] > 0
            key = x // A[i]
            cnt += bisect_right(A, key)
            if A[i] * A[i] <= x:
                cnt -= 1

        return cnt // 2

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

    n = bisect_left(a=A, x=0)  # [0,n)=>負
    z = bisect_left(a=A, x=1)  # [n,z)=>0

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

    print(ans)


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
# 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 = 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
        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)


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送の改変
# aを負0正に分けて処理

def main():
    inf = 10 ** 18 + 1

    def bs_kth_lt_0():
        def negative(e):
            ok, ng = len_p, -1
            cand_ = -cand
            while ok - ng > 1:
                mid = (ng + ok) // 2
                if p[mid] * e > cand_:  # -cand:
                    ok = mid
                else:
                    ng = mid
            return len_p - ok
            # [ok,n)の区間が
            # a[ok] * e < cand を満たす
            # 区間の長さ n - ok = 積がcand未満という条件を満たす候補数になる
            # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

        ok, ng = -inf, 0
        while ng - ok > 1:
            cand = (ng + ok) // 2
            tot = sum(negative(e) for e in m)
            if tot < k:
                ok = cand
            else:
                ng = cand
        return ok

    def bs_kth_gt_0():
        def positive(e, lis):
            ok, ng = -1, len(lis)
            while ng - ok > 1:
                mid = (ng + ok) // 2
                if lis[mid] * e < cand:
                    ok = mid
                else:
                    ng = mid
            return ok + 1
            # [0,ok]の区間が
            # a[ok] * e < cand を満たす
            # ok は 0-indexed なので 1-indexed に直すと、
            # 区間の長さ = 積がcand未満という条件を満たす候補数になる
            # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

        def is_ok(cand):
            tot = 0
            for e in m:
                tot += positive(e, m)
                if e * e < cand:
                    tot -= 1  # 同じもの同士のペアを減らす
            for e in p:
                tot += positive(e, p)
                if e * e < cand:
                    tot -= 1  # 同じもの同士のペアを減らす
            tot //= 2  # (1,2),(2,1)のような同一ペアの二重計上を減らす
            return tot < k

        ok, ng = 0, inf
        while ng - ok > 1:
            cand = (ng + ok) // 2
            if is_ok(cand):
                ok = cand
            else:
                ng = cand
        return ok

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

    m, z, p = [], [], []
    for x in a:
        if x < 0:
            m.append(x)
        elif x == 0:
            z.append(x)
        else:
            p.append(x)

    *m, = sorted(-x for x in m)  # 正に符号変換して昇順ソート
    p.sort()

    len_m = len(m)
    len_z = len(z)
    len_p = len(p)

    cnt_m = len_m * len_p
    cnt_z = len_z * (len_z - 1) // 2 + len_z * (n - len_z)

    if k <= cnt_m:
        # k番目の値は負
        ans = bs_kth_lt_0()
        print(ans)
        return

    elif k <= cnt_m + cnt_z:
        # k番目の値は0
        print(0)
        return
    else:
        # k番目の値は正
        k -= cnt_m + cnt_z  # 正の値の中での順位に直す

        ans = bs_kth_gt_0()
        print(ans)
        return


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送の改変
# aを負0正に分けて処理

def main():
    from bisect import bisect_left

    def bs_kth_lt_0():
        inf = 10 ** 18 + 1
        n = len(p)

        def negative(e):
            ok, ng = n, -1  # len(p), -1
            cand_ = -cand
            while ok - ng > 1:
                mid = (ng + ok) // 2
                if p[mid] * e > cand_:  # -cand:
                    ok = mid
                else:
                    ng = mid
            return n - ok  # len(p) - ok
            # [ok,n)の区間が
            # a[ok] * e < cand を満たす
            # 区間の長さ n - ok = 積がcand未満という条件を満たす候補数になる
            # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

        ok, ng = -inf, 0
        while ng - ok > 1:
            cand = (ng + ok) // 2
            tot = sum(negative(e) for e in m)
            if tot < k:
                ok = cand
            else:
                ng = cand
        return ok

    def bs_kth_gt_0():
        inf = 10 ** 18 + 1

        def positive(e, lis):
            ok, ng = -1, len(lis)
            while ng - ok > 1:
                mid = (ng + ok) // 2
                if lis[mid] * e < cand:
                    ok = mid
                else:
                    ng = mid
            return ok + 1
            # [0,ok]の区間が
            # a[ok] * e < cand を満たす
            # ok は 0-indexed なので 1-indexed に直すと、
            # 区間の長さ = 積がcand未満という条件を満たす候補数になる
            # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

        def is_ok(cand):
            tot = 0
            for lis in (m, p):
                for e in lis:
                    tot += positive(e, lis)
                    if e * e < cand:
                        tot -= 1  # 同じもの同士のペアを減らす
            tot //= 2  # (1,2),(2,1)のような同一ペアの二重計上を減らす
            return tot < k

        ok, ng = 0, inf
        while ng - ok > 1:
            cand = (ng + ok) // 2
            if is_ok(cand):
                ok = cand
            else:
                ng = cand
        return ok

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

    i = bisect_left(a, 0)
    j = bisect_left(a, 1)
    m, z, p = a[:i], a[i:j], a[j:]

    *m, = sorted(-x for x in m)  # 正に符号変換して昇順ソート

    cnt_m = len(m) * len(p)
    cnt_z = len(z) * (len(z) - 1) // 2 + len(z) * (n - len(z))

    if k <= cnt_m:
        # k番目の値は負
        ans = bs_kth_lt_0()
        print(ans)
        return

    elif k <= cnt_m + cnt_z:
        # k番目の値は0
        print(0)
        return
    else:
        # k番目の値は正
        k -= cnt_m + cnt_z  # 正の値の中での順位に直す

        ans = bs_kth_gt_0()
        print(ans)
        return


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送の改変
# aを負0正に分けて処理

def main():
    from bisect import bisect_left

    def bs_kth_lt_0():
        inf = 10 ** 18 + 1

        def negative(e):
            ok, ng = len(p), -1
            while abs(ng - ok) > 1:
                mid = (ng + ok) // 2
                if p[mid] * e > -cand:
                    ok = mid
                else:
                    ng = mid
            return len(p) - ok
            # [ok,n)の区間が
            # a[ok] * e < cand を満たす
            # 区間の長さ n - ok = 積がcand未満という条件を満たす候補数になる
            # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

        ok, ng = -inf, 0
        while abs(ng - ok) > 1:
            cand = (ng + ok) // 2
            tot = sum(negative(e) for e in m)
            if tot < k:
                ok = cand
            else:
                ng = cand
        return ok

    def bs_kth_gt_0():
        inf = 10 ** 18 + 1

        def positive(e, lis):
            ok, ng = -1, len(lis)
            while abs(ng - ok) > 1:
                mid = (ng + ok) // 2
                if lis[mid] * e < cand:
                    ok = mid
                else:
                    ng = mid
            return ok + 1
            # [0,ok]の区間が
            # a[ok] * e < cand を満たす
            # ok は 0-indexed なので 1-indexed に直すと、
            # 区間の長さ = 積がcand未満という条件を満たす候補数になる
            # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

        def is_ok(cand):
            tot = 0
            for lis in (m, p):
                for e in lis:
                    tot += positive(e, lis)
                    if e * e < cand:
                        tot -= 1  # 同じもの同士のペアを減らす
            tot //= 2  # (1,2),(2,1)のような同一ペアの二重計上を減らす
            return tot < k

        ok, ng = 0, inf
        while abs(ng - ok) > 1:
            cand = (ng + ok) // 2
            if is_ok(cand):
                ok = cand
            else:
                ng = cand
        return ok

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

    i = bisect_left(a, 0)
    j = bisect_left(a, 1)
    m, z, p = a[:i], a[i:j], a[j:]

    *m, = sorted(-x for x in m)  # 正に符号変換して昇順ソート

    cnt_m = len(m) * len(p)
    cnt_z = len(z) * (len(z) - 1) // 2 + len(z) * (n - len(z))

    if k <= cnt_m:
        # k番目の値は負
        ans = bs_kth_lt_0()
        print(ans)
        return

    elif k <= cnt_m + cnt_z:
        # k番目の値は0
        print(0)
        return
    else:
        # k番目の値は正
        k -= cnt_m + cnt_z  # 正の値の中での順位に直す

        ans = bs_kth_gt_0()
        print(ans)
        return


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送の改変
# aを負0正に分けて処理

def bs_kth_lt_0():
    inf = 10 ** 18 + 1

    def negative(e):
        ok, ng = len(p), -1
        while abs(ng - ok) > 1:
            mid = (ng + ok) // 2
            if p[mid] * e < cand:
                ok = mid
            else:
                ng = mid
        return len(p) - ok
        # [ok,n)の区間が
        # a[ok] * e < cand を満たす
        # 区間の長さ n - ok = 積がcand未満という条件を満たす候補数になる
        # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

    def is_ok():
        tot = 0
        for e in m:
            tot += negative(e)
        return tot < k

    ok, ng = -inf, 0
    while abs(ng - ok) > 1:
        cand = (ng + ok) // 2
        if is_ok():
            ok = cand
        else:
            ng = cand
    return ok


def bs_kth_gt_0():
    inf = 10 ** 18 + 1

    def positive(e, lis):
        ok, ng = -1, len(lis)
        while abs(ng - ok) > 1:
            mid = (ng + ok) // 2
            if lis[mid] * e < cand:
                ok = mid
            else:
                ng = mid
        return ok + 1
        # [0,ok]の区間が
        # a[ok] * e < cand を満たす
        # ok は 0-indexed なので 1-indexed に直すと、
        # 区間の長さ = 積がcand未満という条件を満たす候補数になる
        # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

    def is_ok(cand):
        tot = 0
        for lis in (m, p):
            for e in lis:
                tot += positive(e, lis)
                if e * e < cand:
                    tot -= 1  # 同じもの同士のペアを減らす
        tot //= 2  # (1,2),(2,1)のような同一ペアの二重計上を減らす
        return tot < k

    ok, ng = 0, inf
    while abs(ng - ok) > 1:
        cand = (ng + ok) // 2
        if is_ok(cand):
            ok = cand
        else:
            ng = cand
    return ok


def main():
    from bisect import bisect_left

    global n, k, a, m, z, p

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

    i = bisect_left(a, 0)
    j = bisect_left(a, 1)
    m, z, p = a[:i], a[i:j], a[j:]

    def combi(n, r):
        if r == 0:
            return 1
        return n * combi(n - 1, r - 1) // r

    cnt_m = len(m) * len(p)
    cnt_z = combi(len(z), 2) + len(z) * (n - len(z))
    # cnt_p = combi(n, 2) - cnt_m - cnt_z

    if k <= cnt_m:
        # k番目の値は負
        ans = bs_kth_lt_0()
        print(ans)
        return

    elif k <= cnt_m + cnt_z:
        # k番目の値は0
        print(0)
        return
    else:
        # k番目の値は正
        k -= cnt_m + cnt_z  # 正の値の中での順位に直す

        *m, = sorted(-x for x in m)  # 正に符号変換して昇順ソート
        ans = bs_kth_gt_0()
        print(ans)
        return


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送
# 関数を切り分けたものはTLEした

def main():
    inf = 10 ** 18 + 1

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

    def is_ok(x):
        """x未満の値はk個未満か"""
        tot = 0
        for a_ in a:
            if a_ < 0:
                l, r = -1, n
                while (r - l) > 1:
                    c = (l + r) // 2
                    if a[c] * a_ < x:
                        r = c
                    else:
                        l = c
                tot += n - r
            else:
                l, r = -1, n
                while (r - l) > 1:
                    c = (l + r) // 2
                    if a[c] * a_ < x:
                        l = c
                    else:
                        r = c
                tot += r
            if a_ * a_ < x:
                tot -= 1
        tot //= 2
        return tot < k

    l, r = -inf, inf
    while (r - l) > 1:
        x = (l + r) // 2
        if is_ok(x):  # x未満の値はk個未満か？
            l = x
        else:
            r = x
        # 「x未満がk個未満」であるxの最大値
    print(l)


if __name__ == '__main__':
    main()
    

Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送
# 写経

def binary_search():
    """ok未満にk個未満の数があるようなokの最大値=k番目"""
    inf = 10 ** 18 + 1

    def positive(e):
        ok, ng = -1, n
        while abs(ng - ok) > 1:
            mid = (ng + ok) // 2
            if a[mid] * e < cand:
                ok = mid
            else:
                ng = mid
        return ok + 1
        # [0,ok]の区間が
        # a[ok] * e < cand を満たす
        # ok は 0-indexed なので 1-indexed に直すと、
        # 区間の長さ = 積がcand未満という条件を満たす候補数になる
        # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

    def negative(e):
        ok, ng = n, -1
        while abs(ng - ok) > 1:
            mid = (ng + ok) // 2
            if a[mid] * e < cand:
                ok = mid
            else:
                ng = mid
        return n - ok
        # [ok,n)の区間が
        # a[ok] * e < cand を満たす
        # 区間の長さ n - ok = 積がcand未満という条件を満たす候補数になる
        # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

    def is_ok(cand):
        tot = 0
        for e in a:
            if e < 0:
                tot += negative(e)
            else:
                tot += positive(e)
            if e * e < cand:
                tot -= 1  # 同じもの同士のペアを減らす
        tot //= 2  # (1,2),(2,1)のような同一ペアの二重計上を減らす
        return tot < k

    ok, ng = -inf, inf
    while abs(ng - ok) > 1:
        cand = (ng + ok) // 2
        if is_ok(cand):
            ok = cand
        else:
            ng = cand
    return ok


def main():
    global n, k, a

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

    ans = binary_search()
    print(ans)


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
# 解説放送
# 写経

def binary_search():
    """ok未満にk個未満の数があるようなokの最大値=k番目"""
    inf = 10 ** 18 + 1

    def positive(e):
        ok, ng = -1, n
        while abs(ng - ok) > 1:
            mid = (ng + ok) // 2
            if a[mid] * e < cand:
                ok = mid
            else:
                ng = mid
        return ok + 1
        # [0,ok]の区間が
        # a[ok] * e < cand を満たす
        # ok は 0-indexed なので 1-indexed に直すと、
        # 区間の長さ = 積がcand未満という条件を満たす候補数になる
        # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

    def negative(e):
        ok, ng = n, -1
        while abs(ng - ok) > 1:
            mid = (ng + ok) // 2
            if a[mid] * e < cand:
                ok = mid
            else:
                ng = mid
        return n - ok
        # [ok,n)の区間が
        # a[ok] * e < cand を満たす
        # 区間の長さ n - ok = 積がcand未満という条件を満たす候補数になる
        # 同じもの同士のペアやペアの二重計上があるので、あとで減らす

    def is_ok(cand):
        tot = 0
        for e in a:
            if e < 0:
                tot += negative(e)
            else:
                tot += positive(e)
            if e * e < cand:
                tot -= 1  # 同じもの同士のペアを減らす
        tot //= 2  # (1,2),(2,1)のような同一ペアの二重計上を減らす
        return tot < k

    ok, ng = -inf, inf
    while abs(ng - ok) > 1:
        cand = (ng + ok) // 2
        if is_ok(cand):
            ok = cand
        else:
            ng = cand
    return ok


def main():
    global n, k, a

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

    ans = binary_search()
    print(ans)


if __name__ == '__main__':
    main()


Fixed submission:
# 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 = 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)


if __name__ == '__main__':
    main()