51nod 1105 第K大的数 【双重二分/二分套二分/两数组任意乘积后第K大数】
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
收藏
关注
数组A和数组B,里面都有n个整数。数组C共有n^2个整数,分别是A[0] * B[0],A[0] * B[1] ......A[1] * B[0],A[1] * B[1]......A[n - 1] * B[n - 1](数组A同数组B的组合)。求数组C中第K大的数。
例如:A:1 2 3,B:2 3 4。A与B组合成的C包括2 3 4 4 6 8 6 9 12共9个数。
Input
第1行:2个数N和K,中间用空格分隔。N为数组的长度,K对应第K大的数。(2 <= N <= 50000,1 <= K <= 10^9) 第2 - N + 1行:每行2个数,分别是A[i]和B[i]。(1 <= A[i],B[i] <= 10^9)
Output
输出第K大的数。
Input示例
3 2 1 2 2 3 3 4
Output示例
9
【代码】:
#include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> #include<vector> #include<cmath> #include<cctype> using namespace std; #define LL long long #define fin freopen("input.txt","r",stdin) #define fout freopen("output.txt","w+",stdout) const int INF = 0x3f3f3f3f; const int N = 50005; const int M = 100005; LL n,m,k,mid; /*数组A同数组B组合乘积,二分查找第K大*/ LL a[N], b[N]; //二分答案 /* 先把a和b排序, 然后确定当前二分的数所在的范围(即是由a中的哪个数组成的) 然后再二分b中匹配的位置,然后每次用n减去 就是小于当前二分数的数字的数量 首先我们枚举一个数组,然后二分另一个数组, 找到 >= x的数目,其实我们就是二分答案, l = a[0]*b[0], r = a[n-1]*b[n-1] 如果 >=mid的数目 */ int ok(LL x) { LL sum = 0, tp; for(LL i=0; i<n; i++){ //枚举a数组,二分b数组 tp = x/a[i]+1; sum += n - (lower_bound(b, b+n,tp) - b); } return sum; } //二分查找 int main() { while(cin >> n >> k) { for(int i=0; i<n; i++) cin >> a[i] >> b[i]; sort(a,a+n); sort(b,b+n); LL l = a[0]*b[0] , r = a[n-1]*b[n-1]; while(l <= r) { mid = (l + r) >> 1; if(ok(mid) >= k) l = mid + 1; else r = mid - 1; } cout << l << endl; } }