zoukankan      html  css  js  c++  java
  • 两个数组各个数相加或相乘变成一个矩阵求第K大

    input

    1<=T<=20

    1<=n<=100000,1<=k<=n*n

    a1 a2 ... an 0<ai<=10000

    b1 b2 ... bn 0<bi<=10000

    output

    第k大的数(包含重复)

    做法:类似字符串的编码解码,这里是解码过程,将k解码为对应的01串,把第K大的数看成一个01串,统计出比1000000000000000000000000000000000大的数有多少个,从而确定第一个数是0还是1,然后第二位也是这样,不断的重复直到找到第K大的数,复杂度为O(2nlog(maxa*maxb))

    a[0]*b[0]<=a[0]*b[1]<=...<=a[0]*b[n-1]

    a[1]*b[0]<=a[1]*b[1]<=..<=a[1]*b[n-1]

    ...

    a[n-1]*b[0]<=a[n-1]*b[1]<=...<=a[n-1]*b[n-1]

    同时从上到下也有这样的性质,所以当a[i]*b[j]>val时,a[i+1]*b[j]>val

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 typedef long long LL;
     6  
     7 const int MAXN = 100010;
     8  
     9 int a[MAXN], b[MAXN];
    10 int T, n;
    11 LL k;
    12  
    13 bool check(int val)//统计比val小的数的个数cnt,看cnt比k大还是比k小
    14 {
    15     LL cnt = 0;
    16     for(int i = 0, j = n - 1; i < n; ++i)
    17     {
    18         while(j >= 0 && a[i] * b[j] > val) --j;
    19         cnt += j + 1;//j+1指每一列数中比val大的数
    20     }
    21     return cnt >= k;
    22 }
    23  
    24 int solve()//二分查找第k大的数
    25 {
    26     int l = a[0] * b[0], r = a[n - 1] * b[n - 1];
    27     while(l < r)
    28     {
    29         int mid = (l + r) >> 1;
    30         if(!check(mid)) l = mid + 1;
    31         else r = mid;
    32     }
    33     return l;
    34 }
    35  
    36 int main()
    37 {
    38     scanf("%d", &T);
    39     while (T--)
    40     {
    41         scanf("%d%I64d", &n, &k);
    42         for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
    43         for(int i = 0; i < n; ++i) scanf("%d", &b[i]);
    44         sort(a, a + n);
    45         sort(b, b + n);
    46         k = (LL)n * n - k + 1;
    47         printf("%d
    ", solve());
    48     }
    49     return 0;
    50 }
    View Code

    input

    1<=T<=10

    1<=n,k<=100000

    a1 a2 ... an an<=10^9

    b1 b2 ... bn bn<=10^9

    output

    第k小的数(不包含重复)

    做法:用大白上的有限队列做法,先将第一列的数放进从小到大的优先队列,每出队一个数就将同一行的下一个数放入队列

    a[0]+b[0]<=a[0]+b[1]<=...<=a[0]+b[n-1]

    a[1]+b[0]<=a[1]+b[1]<=..<=a[1]+b[n-1]

    ...

    a[n-1]+b[0]<=a[n-1]+b[1]<=...<=a[n-1]+b[n-1]

  • 相关阅读:
    Mysql中的递归查询
    让git忽略对已经版本控制的文件的本地修改
    关于c#中逆变和协变的理解
    把之前的相关博客都迁到了博客园~
    结合github pages使用travis CI
    Spring中的Filter、HandlerInterceptor和AOP
    HDU1711 Number Sequence 题解 KMP算法
    HDU1358 Period 题解 KMP算法
    HDU1686 Oulipo 题解 KMP算法
    HDU3336 Count the string 题解 KMP算法
  • 原文地址:https://www.cnblogs.com/cdyboke/p/4925069.html
Copyright © 2011-2022 走看看