第K大数-二分原来还可以这样
来源:互联网 发布:网络谩骂是否可以报警 编辑:程序博客网 时间:2024/04/29 01:04
题目:
数组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 21 22 33 4
Output 示例
9
题目分析:
二分A[0]*B[0] -- mid-- A[N-1]*B[N-1],然后求出小于mid的数,用小于mid的数的个数与N*N-K+1比较,一直到最后二分跳出即为答案。
之前一直不明白为何能够二分到准确的答案,因为如果求第3大,答案应该是8,但是7是不是也满足情况。实际上这是要看二分什么时候跳出。
如果你发现有3个>=K的就跳出了,那么肯定不是最终答案。但是如果你到l>r的时候再跳出,二分过程中肯定有一刻指向的是序列中的某个值。
举例:还是找上面例子中第3大
k=3
l=2,r=12 mid = 7
大于=7的有3个,3>=k; 注意这个时候不能跳出而是另l=mid+1=8
l=8,r=12,mid=10
大于=10的只有1个<k,那么r=mid-1=9;
l=8,r=9,mid=8
这个同第一种情况,l=mid+1=9;
l=9,r=9,mid=9
>=9的个数2个<k,那么r=mid-1=8跳出循环(实际上跳出循环肯定是有一个所指即所求)
那么实际l=8 r=9时所指的就是答案。
代码:
//直接计算第K大
#include <iostream>#include <algorithm>using namespace std;const int MAXN = 50002;__int64 a[MAXN],b[MAXN];__int64 N,K;__int64 cnt(__int64 mid){__int64 ret = 0; __int64 j = 0;for (__int64 i = N-1; i >= 0; -- i){while(j<N){if (b[j]*a[i] < mid)++j;elsebreak;}ret += N-j;}return ret;}void binarySearch(){__int64 l = a[0]*b[0];__int64 r = a[N-1]*b[N-1];__int64 ans = 0;while (l <= r){__int64 mid = (l+r)>>1;if (cnt(mid) >= K){ans = mid;l = mid + 1;}elser = mid - 1;}cout << ans << endl;}int main(){while (cin >> N >> K){//K = N*N - K + 1;for (int i = 0; i < N; ++ i){cin >> a[i] >> b[i];}sort(a,a+N);sort(b,b+N);binarySearch();}return 0;}
//计算第N*N-K+1小数,这里转换一下
#include <iostream>#include <algorithm>using namespace std;const int MAXN = 50002;__int64 a[MAXN],b[MAXN];__int64 N,K;__int64 cnt(__int64 mid){__int64 ret = 0; __int64 j = N-1;for (__int64 i = 0; i < N; ++ i){while(j>=0){if (b[j]*a[i] > mid)--j;elsebreak;}ret += j+1;}return ret;}void binarySearch(){__int64 l = a[0]*b[0];__int64 r = a[N-1]*b[N-1];__int64 ans = 0;while (l <= r){__int64 mid = (l+r)>>1;if (cnt(mid) >= K){ans = mid;r = mid - 1;}elsel = mid + 1;}cout << ans << endl;}int main(){while (cin >> N >> K){K = N*N - K + 1;for (int i = 0; i < N; ++ i){cin >> a[i] >> b[i];}sort(a,a+N);sort(b,b+N);binarySearch();}return 0;}
- 第K大数-二分原来还可以这样
- 原来还可以这样,原来还可以这样。原来还可以这样,原来还可以这样,原来还可以这样
- 原来可以这样二分 -_-
- CSS原来还可以这样用
- 女人原来还可以这样活
- 数组原来还可以这样初始化【转】
- TOhtml,原来vim还可以这样
- javascript原来还可以这样玩
- 原来border还可以这样用
- 原来编程还可以这样学习
- 原来HIBERNATE还可以这样用啊。。。动态表名
- 真是绝了:原来房间还可以这样布置!
- 原来HIBERNATE还可以这样用啊。。。动态表名
- hdu 4187 Alphabet Soup polya原来还可以这样
- POJ 1185(状态压缩原来还可以这样)
- java中HelloWorld原来还可以这样玩
- 随笔 | 让您操碎心的ElasticSearch,原来还可以这样加固安全
- 原来求质数对还可以这样求
- POJ P1988 Cube Stacking 并查集
- UVa 713 - Adding Reversed Numbers
- 如何正确使用C++多重继承
- QueryInterface
- Sprite Kit -- Sprite
- 第K大数-二分原来还可以这样
- dddddddddddddddddd
- Database层和ContentProvider层整理
- 敏捷开发流程总结
- jfinal
- jfinal notes
- jfinal notes(2)
- jfinal note(3)
- jfinal notes continuing