合并两个数组,新数组第k小的元素---二分--九度OJ1534-CSDN博客

51 阅读1分钟

题目1534:数组中第K小的数字

  • 时间限制:2 秒

    内存限制:128 兆

    特殊判题:否

    提交:2005

    解决:436

      • 题目描述:
      • 给定两个整型数组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,1e9]。
      • 输出:
      • 对应每个测试案例,
        输出由A和B中元素两两相加得到的数组c中第K小的数字。
      • 样例输入:
      • 2 2 3
        1 2
        3 4
        3 3 4
        1 2 7
        3 4 5
        
      • 样例输出:
      • 5
        6
        
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N = 1e5 + 7;
    typedef long long LL;
    LL a[N], b[N];
    LL cal(LL a[], LL b[], int n, int m, LL mid) { //返回小于等于mid的两数和的个数
    	LL cnt = 0; int j = m - 1;
    	for (int i = 0; i < n; ++i) {
    		while (j >= 0 && a[i] + b[j] > mid)
    			--j;
    		cnt += 1 + j;
    	}
    	return cnt;
    }
    LL findK(LL a[], LL b[], int n, int m, LL k) {
    	sort(a, a + n);
    	sort(b, b + n);
    	LL l = a[0] + b[0], r = a[n - 1] + b[m - 1];
    	while (l <= r) {
    		LL mid = l + r >> 1;
    		if (k <= cal(a, b, n, m, mid)) r = mid - 1;
    		else l = mid + 1;
    	}
    	return l;
    }
    int main()
    {
    	int n, m; LL k;
    	while (~scanf("%d%d%lld", &n, &m, &k)) {
    		for (int i = 0; i < n; ++i)
    			scanf("%lld", a + i);
    		for (int i = 0; i < m; ++i)
    			scanf("%lld", b + i);
    		printf("%lld\n", findK(a, b, n, m, k));
    	}
    
    	return 0;
    }
    


    数据范围较大,小心int溢出

    \