#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define REP(i, n) for (int i = 0; i < n; i++)
#define ALL(a) (a).begin(), (a).end()
typedef vector<int> vi;
const int INF = 1LL << 60;
const int MOD = 1000000007;
const int MAX_N = 200100;

vi vplus;
vi vminus;
vi vzero;

// index が条件を満たすかどうか
bool m_isOK(int X, int K)
{
    int tmp = 0;
    REP(i, vplus.size())
    {
        int tar;
        if (X < 0)
            tar = (X + 1) / vplus[i] - 1; //tarがXを超えない上限値
        else
            tar = X / vplus[i]; //tarがXを超えない上限値

        auto iter = upper_bound(vminus.begin(), vminus.end(), tar);
        int d = iter - vminus.begin();
        tmp += d;
    }
    if (tmp >= K)
        return true;
    else
        return false;
}

// 汎用的な二分探索のテンプレ
void m_search(int K)
{
    //K番目の数字を知りたい

    //探索区間の初期値
    int left = -INF;
    int right = 1;

    /* どんな二分探索でもここの書き方を変えずにできる！ */
    while (right - left > 1)
    {
        int X = left + (right - left) / 2;

        if (m_isOK(X, K))
            right = X;
        else
            left = X;
    }

    cout << right << endl;
}

// index が条件を満たすかどうか
bool p_isOK(int X, int K)
{
    //X以下の数字がK個以上であることの判定もにぶたん*Nで求める
    int tmpp = 0;
    REP(i, vplus.size())
    {
        int tar;
        if (X < 0)
            tar = (X + 1) / vplus[i] - 1; //tarがXを超えない上限値
        else
            tar = X / vplus[i]; //tarがXを超えない上限値
        auto iter = upper_bound(vplus.begin(), vplus.end(), tar);
        int d = iter - vplus.begin();
        tmpp += d;
    }
    REP(i, vplus.size())
    {
        if (vplus[i] * vplus[i] <= X) //自分自身をへらす
            tmpp--;
    }
    tmpp /= 2;

    int tmpm = 0;
    REP(i, vminus.size())
    {
        int tar;
        if (X < 0)
            tar = (X + 1) / vminus[i] - 1; //tarがXを超えない上限値
        else
            tar = X / vminus[i]; //tarがXを超えない上限値
        auto iter = upper_bound(vminus.begin(), vminus.end(), tar);
        int d = iter - vminus.begin();
        tmpm += d;
    }
    REP(i, vminus.size())
    {
        if (vminus[i] * vminus[i] <= X) //自分自身をへらす
            tmpm--;
    }
    tmpm /= 2;
    return (tmpp + tmpm >= K);
}

// 汎用的な二分探索のテンプレ
void p_search(int K)
{
    //K番目の数字を知りたい
    //X以下の数字がK個以上になる最小のXをにぶたんで求める
    //X以下の数字がK個以上であることの判定もにぶたん*Nで求める
    //すなわちN(logN)^2

    //探索区間の初期値
    int left = -1;
    int right = INF;

    /* どんな二分探索でもここの書き方を変えずにできる！ */
    while (right - left > 1)
    {
        int X = left + (right - left) / 2;

        if (p_isOK(X, K))
            right = X;
        else
            left = X;
    }

    cout << right << endl;
}

signed main()
{
    //  以降 cin の入力元が 'input.txt' になる
    // std::ifstream in("in/sub1_04.txt");
    // std::cin.rdbuf(in.rdbuf());
    int N, K;
    cin >> N >> K;
    REP(i, N)
    {
        int tmp;
        cin >> tmp;
        if (tmp < 0)
        {
            vminus.push_back(tmp);
        }
        else if (tmp == 0)
        {
            vzero.push_back(tmp);
        }
        else
        {
            vplus.push_back(tmp);
        }
    }
    sort(ALL(vminus));
    sort(ALL(vplus));

    if (K <= vminus.size() * vplus.size())
    {
        m_search(K);
        return 0;
    }
    K -= vminus.size() * vplus.size();
    if (K <= vzero.size() * (N - vzero.size()) + vzero.size() * (vzero.size() - 1) / 2)
    {
        cout << 0 << endl;
        return 0;
    }
    K -= vzero.size() * (N - vzero.size()) + vzero.size() * (vzero.size() - 1) / 2;
    reverse(ALL(vminus));
    REP(i, vminus.size())
    {
        vminus[i] *= -1;
    }
    p_search(K);

    return 0;
}

Measured memory_bytes: 2548