• 二分套二分 hrbeu.acm.1211Kth Largest


    Kth Largest

    TimeLimit: 1 Second   MemoryLimit: 32 Megabyte 

    Description

    There are two sequences A and B with N (1<=N<=10000) elements each. All of the elements are positive integers. Given C=A*B, where '*' representing Cartesian product, c = a*b, where c belonging to C, a belonging to A and b belonging to B. Your job is to find the K'th largest element in C, where K begins with 1.

    Input

    Input file contains multiple test cases. The first line is the number of test cases. There are three lines in each test case. The first line of each case contains two integers N and K, then the second line represents elements in A and the following line represents elements in B. All integers are positive and no more than 10000. K may be more than 10000.

    Output

    For each case output the K'th largest number.

    Sample Input

    2

    2 1

    3 4

    5 6

    2 3

    2 1

    4 8

    Sample Output

    24

    8

    解题思路
      双重二分。先对两个序列A,B从大到小排序,然后可以我们进行第一重二分:对要求取的答案二分,即求取的答案在[A[n]*B[n],A[1]*B[1]]之间,取s1=A[n]*B[n],e1=A[1]*B[1],mid=(s1+e1)/2,那么我们去计算在序列C中大于等于这个mid值的个数是多少,当然不是算出这个序列来,而是进行第二次二分。我们对于两个序列可以这样处理,枚举序列A,二分序列B,也就是说对于每个A[i],我们去二分序列B,来计算大于等于mid值的个数。那么我们可以得到结束条件,当大于等于mid值的个数大于等于k,且大于mid值的个数小于k,那么答案就是这个mid。那么时间复杂度就为n*log(n)*log(n^2)了。

     1 #include<iostream>
     2 using namespace std;
     3 #include<cstdio>
     4 #include<cstring>
     5 #define N 10101
     6 #include<algorithm>
     7 int a[N],b[N],tast,k,n;
     8 bool cmp(int a,int b)
     9 {
    10     return a>b;
    11 }
    12 int read()
    13 {
    14     int ans=0,ff=1;
    15     char s;
    16     s=getchar();
    17     while(s<'0'||s>'9')
    18     {
    19         if(s=='-') ff=-1;
    20         s=getchar();
    21     }
    22     while(s>='0'&&s<='9')
    23     {
    24         ans=ans*10+s-'0';
    25         s=getchar();
    26     }
    27     return ans;
    28 }
    29 int find(int l,int r,int t,int m)
    30 {
    31     int mid;
    32     while(l<=r)
    33     {
    34         mid=(l+r)>>1;
    35         if(m*b[mid]>t) 
    36          l=mid+1;
    37         else r=mid-1;
    38     }
    39     return r;
    40 }
    41 int count(int t)
    42 {
    43     int ret=0;
    44     for(int i=1;i<=n;++i)
    45     {/*枚举A中的每一个数字,寻找a[i]*b[j]>t的边界*/
    46         ret+=find(1,n,t,a[i]);
    47     }
    48     return ret;
    49 }
    50 int solve(int l,int r)
    51 {
    52     int mid,ans;
    53     int t1,t2;
    54     while(l<=r)
    55     {
    56         mid=(l+r)>>1;
    57         t1=count(mid);//统计大于mid值的个数
    58         t2=count(mid-1);//统计大于等于mid值的个数
    59         if(t1<k&&t2>=k)/*为什么不是t1==k-1&&t2==k,是为了处理数据重复的情况,这时一定符合t1<k&&t2>=k*/
    60         {
    61             ans=mid;/*找到答案直接跳出*/
    62             break;
    63         }
    64         else if(t2<k) r=mid-1;
    65              else l=mid+1;
    66     }
    67     return ans;
    68 }
    69 int main()
    70 {
    71     tast=read();
    72     while(tast--)
    73     {
    74         n=read();k=read();
    75         for(int i=1;i<=n;++i)
    76         a[i]=read();
    77         for(int i=1;i<=n;++i)
    78         b[i]=read();
    79         sort(a+1,a+n+1,cmp);
    80         sort(b+1,b+n+1,cmp);
    81         printf("%d
    ",solve(a[n]*b[n],a[1]*b[1]));
    82         memset(a,0,sizeof(a));
    83         memset(b,0,sizeof(b));
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    Python实现杨辉三角
    第8.30节 重写Python __setattr__方法实现属性修改捕获
    转:Cookie详解
    第8.29节 使用MethodType将Python __setattr__定义的实例方法与实例绑定
    第8.28节 Python中使用__setattr__定义实例变量和实例方法
    第8.27节 Python中__getattribute__与property的fget、@property装饰器getter关系深入解析
    第8.26节 重写Python类中的__getattribute__方法实现实例属性访问捕获
    关于open函数文件打开模式的有意思的一个现象
    第8.25节 Python风格的__getattribute__属性访问方法语法释义及使用
    转:关于Python中的lambda,这篇阅读量10万+的文章可能是你见过的最完整的讲解
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5589312.html
Copyright © 2020-2023  润新知