#include<bits/stdc++.h>
#include <numeric>

using namespace std;
typedef long long ll;
#define rep(i, n) for (ll i = 0; i < (ll)(n); ++i)
#define erep(i, n) for (ll i = 0; i <= (ll)(n); ++i)
#define FOR(i,a,b) for (ll i = (a); i < (ll)(b); ++i)
#define EFOR(i,a,b) for (ll i = (a); i <= (ll)(b); ++i)
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } }

// 約数列挙
vector<ll> divisor(ll n) {
    vector<ll> ret;
    for(ll i = 1; i * i <= n; i++) {
        if(n % i == 0) {
            ret.push_back(i);
            if(i * i != n) ret.push_back(n / i);
        }
    }
    sort(begin(ret), end(ret));
    return ret;
}

// 素数判定
bool isPrime(ll n) {
    ll i = 2;
    while (i*i <= n) {
        if(n%i==0) return false;
        i++;
    }
    return true;
}

// ll(1e18)でちゃんと型指定しないと後ろの+5が誤差で無視されるらしい
const ll INF = ll(1e18)+5;

int main() {
    ll n,k; cin >> n >> k;
    vector<ll> a(n);
    rep(i, n) cin >> a[i];
    sort(a.begin(), a.end());

    // 2重の二分探索でとく

    // 外側の二分探索用は答えの数を求める
    // 答えとして考えられる範囲(a[i]の最大値=1e9 * 1e9 = 1e18の±)に対して二分探索を行う
    ll l = -INF, r = INF;
    // l,rが並び合うときのlが答えとなる
    while(l+1 < r) {
        // xが先頭からk番目の候補値
        ll x = (l+r)/2;

        // ラムダ関数で計算
        bool ok = [&]{

            // x未満のペアがいくつかを管理する変数
            ll tot = 0;

            // 全てのaを探索していく
            rep(i, n) {

                // 内側の二分探索
                // a[i]が正か負で場合わけ

                if(a[i] < 0) {
                    // a[i]が負の場合
                    // 基本的には正の場合と同じ
                    // a[i]が負の場合は二分探索で求まった位置から配列の最後までがx未満になるということは注意
                    ll l = -1, r = n;
                    while(l+1<r) {
                        ll c = (l+r)/2;
                        // ここの判定条件が正の場合と逆になる
                        if (a[c]*a[i] < x) r=c;
                        else l=c;
                    }
                    // 上にも書いたようにa[0]~a[c]でなく、a[r]~a[n-1]までがx未満の数
                    tot += n-r;
                } else {
                    // a[i]が正の場合
                    // 最終的には l+1 == rとなる
                    // 全てがNGの場合はr = 0になって欲しいので、l=-1が初期値となる
                    ll l = -1, r = n;

                    // 二分探索
                    while(l+1<r) {
                        ll c = (l+r)/2;
                        // 今のa[i](正の値) かける 二分探索の候補の配列の中央の値(c)がx未満なら、 cより前の値とa[i]の掛け算は全てx未満になると言える
                        // そうであれば、leftをcに,
                        if (a[c]*a[i] < x) l=c;
                        // 逆にそうでなければ、x未満となる数はcより左側にいるのでr=cにする
                        else r=c;
                    }
                    // 先頭からrまでの要素がa[i]と掛け合わせたときにx未満になる数なので、それを足しておく
                    tot += r;
                }
                // 自分自身とはペアに慣れないの
                // 自分自身との掛け算がx未満であれば。上の二分探索で求めた中に含まれてしまうので、1引いておく
                if(a[i]*a[i] < x) tot--;
            }
            // (a[4],a[10])のペアと(a[10],a[4])のペアといった感じで、同じペアだけど、順番が違うだけというのが含まれているので、半分に割ってあげる
            tot /= 2;
            // 最終的なx未満のペア数がk未満なら、ok
            return tot < k;
        }();
        
        // xがk未満なら, 答えはxより右側にあるので、l=xにする
        // x以上なら左側に答えがあるので、r=xにする
        if (ok) l = x; else r = x;
    }
    // 最終的に決まった位置のlが答えとなる
    cout << l << endl;
    return 0;
}


Measured memory_bytes: 1792