数组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
为什么会想到用二分呢....不可思议...
直接二分第K大的数,L=a[1]*b[1] R=a[n]*b[n]
对于mid我们看看他是不是排在第K位上。
注意他问的是第K大!!大,但是处理都是按小的进行处理的,所以我们k变一下,k=n*n-k.
之后检查函数来检查mid
我们枚举a,对于当前a,我们倒着枚举b。
如果a*b的值比
mid大,我们b--。
如果小了,直接break
统计每个a循环中j的数量
#include<iostream>
#include<string.h>
#include<set>
#include<algorithm>
using namespace std;
long long n,m,k;
long long a[60000],b[60000];
long long check(long long num)
{
long long ans=0;
long long j=n;
ans=0;
for(long long i=1;i<=n;i++)
{
for(;j>=0;)
{
if(a[i]*b[j]>num)
j--;
else
break;
}
ans+=j;
}
return ans;
}
int main()
{
long long low,high,i,j,k;
cin>>n>>k;
k=n*n-k+1;
for(i=1;i<=n;i++)
cin>>a[i]>>b[i];
sort(a+1,a+1+n);
sort(b+1,b+1+n);
low=a[1]*b[1];
high=a[n]*b[n];
long long mid;
long long ans=0;
while(high-low>1) {
mid=(low+high)>>1;
if(check(mid)>=k) {
ans=mid;
high=mid;
}
else low=mid;
}
cout<<ans<<endl;
return 0;
}
#include<string.h>
#include<set>
#include<algorithm>
using namespace std;
long long n,m,k;
long long a[60000],b[60000];
long long check(long long num)
{
long long ans=0;
long long j=n;
ans=0;
for(long long i=1;i<=n;i++)
{
for(;j>=0;)
{
if(a[i]*b[j]>num)
j--;
else
break;
}
ans+=j;
}
return ans;
}
int main()
{
long long low,high,i,j,k;
cin>>n>>k;
k=n*n-k+1;
for(i=1;i<=n;i++)
cin>>a[i]>>b[i];
sort(a+1,a+1+n);
sort(b+1,b+1+n);
low=a[1]*b[1];
high=a[n]*b[n];
long long mid;
long long ans=0;
while(high-low>1) {
mid=(low+high)>>1;
if(check(mid)>=k) {
ans=mid;
high=mid;
}
else low=mid;
}
cout<<ans<<endl;
return 0;
}
另外一个检测方法
- LL check(LL x) {
- LL sum = 0;
- for(int i = n; i >= 1; i--) {
- int t = lower_bound(B + 1, B + 1 + n, (x - 1) / A[i] + 1) - B;
- sum += n - t + 1;
- if(sum == 0) break;
- }
- return sum;
- }