第k小数据

给定两个整型数组A和B(未排序)。我们将A和B中的元素两两相加可以得到数组C。
譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6]。
现在给你数组A和B,求由A和B两两相加得到的数组C中,第K小的数字。
 

输入格式输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为三个整数m,n, k(1<=m,n<=100000, 1<= k <= n *m):n,m代表将要输入数组A和B的长度。
紧接着两行, 分别有m和n个数, 代表数组A和B中的元素。数组元素范围为[0,1e8]。
输出格式对应每个测试案例,
输出由A和B中元素两两相加得到的数组c中第K小的数字。
样例输入

2 2 3
1 2
3 4
3 3 4
1 2 7
3 4 5
样例输出

5
6

#include <stdio.h>  
#include <iostream>  
#include <algorithm> 
#include <math.h>  
#include <string.h>  
using namespace std;
int a[100002];
int b[100002];  
int n,m,k;
int cal(int v)
{
    int l,r,mid,i,d=0;
    int min,max;
    for(i=1;i<=n;i++)
    {
        min=a[i]+b[1];
        max=a[i]+b[m];
        if(v<min)
            break;
        if(v>=max)
        {
            d+=m;
            continue;
        }

        l=1,r=m;
        while(l<=r)
        {
            mid=(l+r)/2;
            if(v<(a[i]+b[mid])) r=mid-1;
            else                 l=mid+1;
        }
        if(v!=(a[i]+b[l]))    l--;
        d += l;
    }
    return d;
}

int find(int l,int r,int k)
{
    int mid,i;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(k<=cal(mid)) r=mid-1;
        else             l=mid+1;
    }
    return l;
}
int main()
{
    int i,j,l,r;
    while(scanf("%d %d %d",&n,&m,&k)!=EOF)
    {
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=m;i++)
        scanf("%d",&b[i]);
    sort(&a[1],&a[n+1]);
    sort(&b[1],&b[m+1]);
    l=a[1]+b[1];
    r=a[n]+b[m];
    printf("%d\n",find(l,r,k));
    }
    return 0;
}

 

posted @ 2017-12-10 14:00  萌新上路  阅读(138)  评论(0编辑  收藏  举报