zoj3617(二分)

来源:互联网 发布:纬地软件 编辑:程序博客网 时间:2024/06/08 12:37

8G Island

Time Limit: 3 Seconds      Memory Limit: 32768 KB

8g Island has N boys and M girls. Every person has a "charm value". When a boy with charm value t1 and a girl with charm value t2 get together, their "8g value" is t1*t2. Every year the king will choose the Kth greatest number from all the N*M possible 8g values as the lucky number of the year. People on the island knows nothing but 8g, so they ask you to help them find the lucky number.

Input

The input contains multiply test cases(<= 10). Each test case contains three parts:

    1 Three integers NM(1 <= N,M <= 100000) and K(1 <= K <= N*M) in a line, as mentioned above.

    N integers in a line, the charm value of each boy.

    M integers in a line, the charm value of each girl.

    All the charm values are integers between 1 and 100000(inclusive).

Process to the end-of-file.

Output

For each test case print a single line that contains the lucky number.

Sample Input

3 2 31 2 31 22 2 11 11 12 2 41 11 1

Sample Output

311


参考:http://blog.csdn.net/YZBYZZ/article/details/18455047?locationNum=10

题意:
两个数组,元素个数分别为n和m。两两相乘可得n*m个数,求第k大的数。

思路:
本渣是听了别人二分的想法后才写出的。
两数组皆 非升序 排序。

首先,二分枚举第k大的数可能是多少。
假设当前枚举到mid,则计算大于等于mid的数有多少个。设之为tmp个。
若tmp > k,说明 第k大的数比mid大
若tmp < k,说明 第k大的数比mid小
若tmp = k, 分两种情况:
若n*m个数中存在等于mid的,则mid为第k大的数
否则,第k大的数比mid大

其中,在找大于等于mid的数有多少个时,采用的是枚举第一个数组,二分第二个数组的方法。
同理,在找是否存在等于mid的数也是采用同样的方法。

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;typedef long long ll;ll a[100005];ll b[100005];int n,m;ll k;bool cmp(const ll x,const ll y){return x>y;}ll B_search_b(ll a,ll x)   //二分ai时对应b中结果大于等于x的元素个数 {ll low=0,high=m-1;while(low<=high){ll mid=(low+high)>>1;if(a*b[mid]<x)high=mid-1;elselow=mid+1;}return low;}ll Selection_a(ll x)         //选择数为x时大于等于x的数的个数 {ll sum=0;for(int i=0;i<n;i++){sum+=B_search_b(a[i],x);}return sum;}bool find_in_b(ll a,ll x){ll low=0,high=m-1;while(low<=high){ll mid=(low+high)>>1;if(a*b[mid]==x)return true;else if(a*b[mid]<x)high=mid-1;elselow=mid+1;}return false;}bool find_x(ll x){for(int i=0;i<n;i++){if(find_in_b(a[i],x))return true;}return false;}ll BinaryResearch(ll low,ll high){ll result=0;while(low<=high){ll mid=(low+high)>>1;ll tmp=Selection_a(mid);if(tmp==k){if(find_x(mid)){result=mid;break;}else low=mid+1;}else if(tmp>k)    //mid小于第k大的数 {low=mid+1;result=mid;}else high=mid-1;}return result;}int main(){while(~scanf("%d%d%lld",&n,&m,&k)){memset(a,0,sizeof(a));memset(b,0,sizeof(b));for(int i=0;i<n;i++)scanf("%lld",&a[i]);for(int i=0;i<m;i++)scanf("%lld",&b[i]);sort(a,a+n,cmp);sort(b,b+m,cmp);printf("%lld\n",BinaryResearch(a[n-1]*b[m-1],a[0]*b[0]));}}

数组一定要开成long long不然wa惨了。


原创粉丝点击