http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105
第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)
输出第K大的数。
3 2 1 2 2 3 3 4
9
好巧妙的二分套二分啊,套路啊= =
我们可以对这个数的大小进行二分,判断一下小于等于这个mid的有多少个数,有多少个数不就说明这个数排第几吗,只要找到一个mid小于等于他的数==k就说明这是第K小的数,
题目的第K大也就是第N*N-K+1小,在统计小于等于mid的数的个数时,也要用二分,我们可以先对AB排序然后枚举每一个Ai,二分查找最多能匹配多少个Bj,累加即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define LL long long 7 LL inf = (LL)1e18+5; 8 LL A[50005], B[50005]; 9 LL cal(LL K,LL N ) 10 { 11 LL r = 0; 12 for (int i = 1;i <= N;++i) 13 { 14 LL x = K / A[i]; 15 if (x < B[1])continue; 16 LL k = upper_bound(B + 1, B + 2 + N, x) - B; 17 r += k - 1; 18 } 19 return r; 20 } 21 int main() 22 { 23 LL N, K, i; 24 cin >> N >> K; 25 for (i = 1;i <= N;++i)scanf("%lld%lld", A + i, B + i); 26 sort(A + 1, A + N + 1); 27 sort(B + 1, B + 1 + N); 28 A[N + 1] = B[N + 1] = inf; 29 A[0] = B[0] = -1; 30 LL l = 1,r = 1e18; 31 K = N*N - K + 1; 32 while (l < r) { 33 LL mid = l + (r - l) / 2; 34 if (cal(mid,N) < K) l = mid + 1; 35 else r = mid; //为了防止答案是mid但是有许多重复的导致cal返回值大于k,我们在这里让r=mid仍然使得mid可以被查找到,而不是被忽略 36 } 37 printf("%lld\n", l); 38 return 0; 39 }