use std::cmp::Ordering::*;
use std::io::{stdin, Read};

#[allow(unused_macros)]
macro_rules! parse {
    ($it: ident ) => {};
    ($it: ident, ) => {};
    ($it: ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
}

#[allow(unused_macros)]
macro_rules! parse_val {
    ($it: ident, [$t:tt; $len:expr]) => {
        (0..$len).map(|_| parse_val!($it, $t)).collect::<Vec<_>>();
    };
    ($it: ident, ($($t: ty),*)) => {
        ($(parse_val!($it, $t)),*)
    };
    ($it: ident, $t: ty) => {
        $it.next().unwrap().parse::<$t>().unwrap()
    };
}

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    parse!(it, n: usize, k: usize, a: [i64; n]);
    let an = a.iter().filter(|x| **x < 0).map(|x| *x).collect::<Vec<_>>();
    let az = a
        .iter()
        .filter(|x| **x == 0)
        .map(|x| *x)
        .collect::<Vec<_>>();
    let ap = a.iter().filter(|x| **x > 0).map(|x| *x).collect::<Vec<_>>();

    let nn = an.len();
    let nz = az.len();
    let np = ap.len();

    let nrn = nn * np;
    let nrp = nn * (nn - 1) / 2 + np * (np - 1) / 2;
    let nrz = n * (n - 1) / 2 - nrn - nrp;

    if k <= nrn {
        let mut an = an;
        an.sort();
        let mut ap = ap;
        ap.sort();
        let mut ng = an[0] * ap[ap.len() - 1] - 1;
        let mut ok = 0;
        while ok - ng > 1 {
            let x = (ok + ng) / 2;
            let mut count = 0;
            for i in 0..ap.len() {
                let b = if x % ap[i] == 0 {
                    x / ap[i]
                } else {
                    x / ap[i] - 1
                };
                let mut j = an
                    .binary_search_by(|item| if *item <= b { Less } else { Greater })
                    .unwrap_err();
                count += j;
            }
            if count < k {
                ng = x
            } else {
                ok = x
            }
        }
        println!("{}", ok);
    } else if k <= nrn + nrz {
        println!("{}", 0);
    } else {
        let k = k - nrn - nrz;
        let mut an = an.iter().map(|x| -(*x)).collect::<Vec<_>>();
        an.sort();
        let mut ap = ap;
        ap.sort();
        let mut ng = 0;
        let mut ok = std::i64::MAX - 1;
        while ok - ng > 1 {
            let x = (ok + ng) / 2;
            let mut count = 0;

            let al = vec![&ap, &an];
            for ia in 0..2 {
                let ap = al[ia];
                for i in 0..ap.len() {
                    let probe = x / ap[i];
                    let mut j = ap
                        .binary_search_by(|item| if *item <= probe { Less } else { Greater })
                        .unwrap_err();
                    if j == 0 {
                        continue;
                    }
                    if ap[j - 1] >= ap[i] {
                        j -= 1;
                    }
                    count += j;
                }
            }
            assert_eq!(count % 2, 0);
            count /= 2;

            if count < k {
                ng = x;
            } else {
                ok = x;
            }
        }
        println!("{}", ok);
    }
}

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        ";
        solve(s);
    }
}


Measured memory_bytes: 12540