题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105
很神奇的双层二分……
第一层二分答案 m,看这个数能否做 a[i]*b[j] 的第 k 大的数。判断的时候是计数有多少个a[i]*b[j] > m,先枚举 a[i],再用二分找到与 a[i] 相乘大于 m 的最小的 b[j](数组 a 和数组 b 事先已经从小到大排好序了),那么从 b[j] 开始,后面所有的数和 a[i] 相乘都会大于 m,累加 n-j+1 即为a[i]*b[j]中 大于 m 的个数,用这个数和 k 相比较就能知道这个数是比 第K大的数大了还是小了。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL maxn = 1e5 + 10;
LL a[maxn];
LL b[maxn];
LL n, k;
LL bin(LL x, LL ai){
LL l = 0;
LL r = n - 1;
LL ret = 0;
while (l < r){
LL m = (l + r) >> 1;
if (b[m] * ai > x){
r = m;
}else{
l = m + 1;
}
}
if (b[r] * ai > x)
return n - r;
return n - r - 1;
}
bool check(LL x){
LL cnt = 0;
for (LL i=0; i<n; i++){
cnt += bin(x, a[i]);
}
return cnt+1 <= k;
}
LL Bin(){
LL l = a[0] * b[0];
LL r = a[n-1] * b[n-1];
LL ret;
while (l <= r){
LL m = (l + r) >> 1;
if (check(m)){
r = m - 1;
ret = m;
}else{
l = m + 1;
}
}
return ret;
}
int main()
{
scanf("%lld%lld", &n, &k);
for (LL i=0; i<n; i++) scanf("%lld%lld", &a[i], &b[i]);
sort(a, a+n);
sort(b, b+n);
cout << Bin() << endl;
return 0;
}