第K小数(二分)

第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;
}
posted @ 2016-11-10 17:23  抽空的太阳  阅读(123)  评论(0编辑  收藏  举报