1.第K小数 (number.cpp/c/pas)

【问题描述】

有两个正整数数列,元素个数分别为N和M。从两个数列中分别任取一个数 相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少。

【输入格式】

输入文件名为number.in。

输入文件包含三行。

第一行为三个正整数N,M和K。

第二行为N个正整数,表示第一个数列。

第三行为M个正整数,表述第二个数列。

【输出格式】

输出文件名为number.out。

输出文件包含一行,一个正整数表示第K小数。

【输入输出样例1】

number.in

2 3 4

1 2

2 1 3

 

number.out  

3

【输入输出样例2】

number.in

5 5 18

7 2 3 5 8

3 1 3 2 5

 

number.out  

16

【数据规模与约定】

11.10 noip模拟试题

11.10 noip模拟试题

 

二分

/*
考试的时候也想到了二分 但是想的是二分套二分 有整数除整数 精度有问题
自己的思路是 二分的每一个X 枚举A序列 算出B中的元素 二分找到位置 这之前的都ok
但是精度有问题 有问题.... O(logMX*n*logm)
正解就很好地避免了这个问题
差不多的思路 二分 然后循环A序列
精华之处在于 每次检验B的时候是沿着上一个Ai确定的位置
因为排好序之后 就很好的具有了这个性质 复杂度 O(logMX*(n+m)) 
*/
#include<cstdio>
#include<algorithm>
#define maxn 200010
#define ll long long
using namespace std;
ll n,m,k,a[maxn],b[maxn],c[maxn],ans,num;
ll init(){
    ll x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
ll Judge(ll x){
    ll cnt=0,p=m;
    for(int i=1;i<=n;i++){
        while(b[p]*a[i]>x&&p)p--;
        cnt+=p;
    }
    return cnt;
}
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+1+n);sort(b+1,b+1+m);
    ll l=0,r=a[n]*b[m];
    while(l<=r){
        ll mid=(l+r)/2;
        if(Judge(mid)>=k){
            r=mid-1;ans=mid;
        }
        else l=mid+1;
    }
    printf("%I64d\n",ans);
    return 0;
}
View Code

相关文章: