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 N, M(1 <= N,M <= 100000) and K(1 <= K <= N*M) in a line, as mentioned above.
2 N integers in a line, the charm value of each boy.
3 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 3 1 2 3 1 2 2 2 1 1 1 1 1 2 2 4 1 1 1 1
Sample Output
3 1 1
参考: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;
else
low=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;
else
low=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惨了。