zoukankan      html  css  js  c++  java
  • ACM_求第k大元素(两次二分)

    求第k大

    Time Limit: 6000/3000ms (Java/Others)

    Problem Description:

    给定两个数组A和B,大小为N,M,每次从两个数组各取一个数相乘放入数组C,最终得到一个N*M的数组C。求C中第K大的数。

    Input:

    输入包含多组测试数据,每组数据首先输入两个整数N,M,K,接下来一行有N个整数Ai,再接下来一行有M个整数Bi。(1≤N,M≤10^5,1≤Ai,Bi≤10^5,1≤K≤N*M)

    Output:

    对于每组数据,输出答案。

    Sample Input:

    3 2 2
    1 2 3
    1 2
    
    2 2 1
    1 1
    1 1

    Sample Output:

    4
    1
    解题思路:由于数据非常大,因此考虑二分来做:先对两个数组降序排,然后外层二分查找第k大元素,内层二分查找当前mid在数组C中排第几并作为外层二分查找的条件,最终的答案就是l-1,详解看代码。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn=1e5+5;
     5 int n,m;LL k,l,r,mid,ans,A[maxn],B[maxn];
     6 inline LL read(){
     7     LL x=0,f=1;char ch=getchar();
     8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    10     return x*f;
    11 }
    12 inline void print(LL x){
    13     if(x<0)putchar('-'),x=-x;
    14     if(x>9)print(x/10);
    15     putchar(x%10+'0');
    16 }
    17 bool check(LL mid){
    18     LL cnt=0;
    19     for(int i=0;i<n;++i){
    20         int lt=0,rt=m-1;
    21         while(lt<=rt){///二分找b数组中某个元素与当前A[i]乘积不小于mid的最大下标lt-1
    22             int midt=(lt+rt)>>1;
    23             if(A[i]*B[midt]>=mid)lt=midt+1;///说明可能还有更小的元素与A[i]相乘之后不小于mid,则往右边找
    24             else rt=midt-1;///否则往左边找
    25         }
    26         cnt+=lt;///退出条件是rt=lt-1,而下标是0开始的,所以lt不用减1,累加当前满足条件的个数
    27     }
    28     return cnt>=k;
    29 }
    30 int main(){///时间复杂度为log2(nm)*n*log2(m)
    31     while(~scanf("%d%d%lld",&n,&m,&k)){
    32         for(int i=0;i<n;++i)A[i]=read();
    33         for(int i=0;i<m;++i)B[i]=read();
    34         sort(A,A+n,greater<LL>());///降序排
    35         sort(B,B+m,greater<LL>());
    36         l=A[n-1]*B[m-1],r=A[0]*B[0];
    37         while(l<=r){///二分找第k大元素(即两个数的乘积)
    38             mid=(l+r)>>1;
    39             if(check(mid))l=mid+1;///说明mid可以更大,继续往右边找
    40             else r=mid-1;///否则往左边找
    41         }
    42         print(l-1);puts("");
    43     }
    44     return 0;
    45 }
  • 相关阅读:
    sql中not exists的用法
    jsp中target="_blank"的用法
    jsp 运用 session 登录输出
    jsp留言板
    编写JSP 实现用户登录并判断用户或密码
    jsp打印九九乘法表
    jsp输出当前时间
    jsp输出金字塔
    jsp输出5的阶乘
    jdbc练习3
  • 原文地址:https://www.cnblogs.com/acgoto/p/10047077.html
Copyright © 2011-2022 走看看