第K小数
问题描述:
有两个正整数数列,元素个数分别为N和M。从两个数列中分别任取一个数
相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少。
输入格式:
输入文件包含三行。
第一行为三个正整数N,M和K。
第二行为N个正整数,表示第一个数列。
第三行为M个正整数,表述第二个数列。
输出格式:
输出文件包含一行,一个正整数表示第K小数。
数据规模与约定:
1<=n<=200000
1<=m<=200000
1<=k<=20000010000
元素大小<=10^9
#include<iostream>
#include<cstdio>
#include<algorithm>
#define lon long long
using namespace std;
const int maxn=200010;
lon n,m,k,tot,a[maxn],b[maxn],s[maxn];
lon init()
{
lon f=1,x=0;char c=getchar();
while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f*x;
}
bool can(lon mid)
{
lon sum=0,j=m;
for(int i=1;i<=n;i++)
{
while(j>=1&&a[i]*b[j]>mid) j--;
sum=sum+j;
}
if(sum>=k)
return 1;
return 0;
}
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
n=init(),m=init(),k=init();
for(int i=1;i<=n;i++) a[i]=init();
for(int i=1;i<=m;i++) b[i]=init();
sort(a+1,a+n+1);
sort(b+1,b+m+1);
lon l=0,r=a[n]*b[m],mid,ans;
while(l<=r)
{
mid=(l+r)>>1;
if(can(mid))
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
cout<<ans;
fclose(stdin);fclose(stdout);
return 0;
}