F 乘法

链接:https://ac.nowcoder.com/acm/contest/3979/F
来源:牛客网

题意:给出n个数的数列和m个数的数列;

两两相乘,求第k大的数;

思路:将其中一个序列排序,然后进行二分

在本代码里我们将b数组进行排序,然后根据a数组计算数量去判断check进行二分

那么如何二分的依据是什么呢?

自然是根据给出的k值,我们先给L R定边界;

然后求出>=mid的数,根据这一条件进行二分;

那么如何求出这个数呢,我们枚举a数列,求出每一个数在b数组里能够满足的个数即可

思路到此就算结束;不过有些细节问题;

1.在求个数的时候,lower_bound跟upper_bound边界问题需要想想

2.其中 floor是向下取整(比如2.5为2,-2.5为3) ceil是向上取整(比如2.5为3,-2.5为2)

3.用lower_bound跟upper_bound求出来的下标是从1开始的

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define pb push_back
 5 #define lson root<<1,l,midd
 6 #define rson root<<1|1,midd+1,r
 7 const int M=1e6+6;
 8 const ll inf=1e13;
 9 ll a[M],b[M];
10 int n,m;
11 ll k;
12 ll check(ll x){
13     ll countt=0;
14     for(int i=1;i<=n;i++){///在b数组里找哪些数乘当前a[i]会大于等于x,记录这个数有几个
15         ll y;
16         if(a[i]<0){
17             if(x<=0)
18                 y=x/a[i];
19             else
20                 y=floor((double)x/(double)a[i]);
21             countt+=upper_bound(b+1,b+1+m,y)-b-1;
22         }
23         else if(a[i]==0&&x<=0)
24             countt+=m;
25         else if(a[i]>0){
26             if(x<=0)
27                 y=x/a[i];
28             else
29                 y=ceil((double)x/(double)a[i]);
30             countt+=m-(lower_bound(b+1,b+1+m,y)-b-1);
31         }
32     }
33     return countt;
34 }
35 int main(){
36  
37     scanf("%d%d%lld",&n,&m,&k);
38     for(int i=1;i<=n;i++)
39         scanf("%lld",&a[i]);
40     for(int i=1;i<=m;i++)
41         scanf("%lld",&b[i]);
42  
43     sort(b+1,b+1+m);
44     ll l=-inf,r=inf;
45     while(l<=r){
46         ll midd=(l+r)>>1;
47         if(check(midd)<k)
48             r=midd-1;
49         else
50             l=midd+1;
51     }
52     printf("%lld\n",r);
53     return 0;
54 }

 

posted @ 2020-03-11 16:05  古比  阅读(349)  评论(0编辑  收藏  举报