您的位置:首页 > 其它

51NOD 1105 第K大的数(二分好题)

2016-07-15 21:36 507 查看
传送门

数组A和数组B,里面都有n个整数。数组C共有n^2个整数,分别是A[0] * B[0],A[0] * B[1] ……A[1] * B[0],A[1] * B[1]……A[n - 1] * B[n - 1](数组A同数组B的组合)。求数组C中第K大的数。

例如:A:1 2 3,B:2 3 4。A与B组合成的C包括2 3 4 4 6 8 6 9 12共9个数。

Input

第1行:2个数N和K,中间用空格分隔。N为数组的长度,K对应第K大的数。(2 <= N <= 50000,1 <= K <= 10^9)

第2 - N + 1行:每行2个数,分别是A[i]和B[i]。(1 <= A[i],B[i] <= 10^9)

Output

输出第K大的数。

Input示例

3 2

1 2

2 3

3 4

Output示例

9

解题思路:

其实我们看到数据范围的时候就已经知道了这肯定是一个n*log(n)的算法,也就是二分,其实这是一个二分里面在套一个二分的题目,首先我们枚举一个数组,然后二分另一个数组,找到 >= x的数目,其实我们就是二分答案,l = a[0]*b[0], r = a[n-1]*b[n-1] 如果 >=mid的数目

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;
typedef long long LL;
const int MAXN = 5e4+5;
LL a[MAXN], b[MAXN];
LL Judge(LL x, int n)///找有多少a[i]*b[j] >= x的数
{
LL sum = 0, tp;
for(int i=n-1; i>=0; i--)///枚举a数组,二分b数组
{
if(x % a[i])
tp = x/a[i]+1;
else
tp = x/a[i];
int tmp = lower_bound(b,b+n,tp)-b;
sum += n-tmp;
if(sum == 0)
break;
}
return sum;
}
int main()
{
int n, k;
while(~scanf("%d%d",&n,&k))
{
for(int i=0; i<n; i++)
scanf("%I64d%I64d",&a[i],&b[i]);
sort(a, a+n);
sort(b, b+n);
LL l = a[0]*b[0], r = a[n-1]*b[n-1];
while(l <= r)///二分答案
{
LL mid = (l+r)>>1;
LL tmp = Judge(mid, n);
if(tmp < k)///与普通二分的比较 不要思维定势
r = mid-1;
else
l = mid+1;
}
printf("%I64d\n",l-1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: