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 }