• poj 3579 Median 二分套二分 或 二分加尺取


    Median
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 5118   Accepted: 1641

    Description

    Given N numbers, X1X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i  j  N). We can get C(N,2)differences through this work, and now your task is to find the median of the differences as quickly as you can!

    Note in this problem, the median is defined as the (m/2)-th  smallest number if m,the amount of the differences, is even. For example, you have to find the third smallest one in the case of = 6.

    Input

    The input consists of several test cases.
    In each test case, N will be given in the first line. Then N numbers are given, representing X1X2, ... , XN, ( X≤ 1,000,000,000  3 ≤ N ≤ 1,00,000 )

    Output

    For each test case, output the median in a separate line.

    Sample Input

    4
    1 3 2 4
    3
    1 10 2
    

    Sample Output

    1
    8

    Source

    题意:给你N个数字,求这些数字两两之差的绝对值的中位数
    二分套二分:核心还是要抓住<x的数量>=m(内层二分)最小x(外层二分)-1才是该序列中的第m小的数,有不理解的话可以看本博客另一篇讲的很详细的文章
    下面的第一份代码是使用了lower_bound,复杂度是n(logn)*(logn);时间是563ms#include<cstdio>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #include <set>
    using namespace std;
    #define MM(a) memset(a,0,sizeof(a))
    typedef long long LL;
    typedef unsigned long long ULL;
    const int mod = 1000000007;
    const double eps = 1e-10;
    const int inf = 0x3f3f3f3f;
    int  a[100005];
    long long   l,r,m,n;
    int ok(int  x)
    {
        int  cnt=0;
        for(int i=1;i<=n;i++)
            cnt+=lower_bound(a+i,a+n+1,a[i]+x)-(a+i)-1;
    //lower_bound降低时间复杂度 return cnt>=m; } int main() { while(~scanf("%lld",&n)) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); m=n*(n-1)/2; if(m%2==0) m=m/2; else m=(m+1)/2; l=0,r=a[n]-a[1]; while(r-l>1) { int mid=(r+l)>>1;///枚举得到<x的数量>=m的最小x; if(ok(mid)) r=mid; else l=mid; } printf("%lld ",r-1); } return 0; }

      有个小技巧是在ok()函数内统计绝对值<x的数量可以不适用lower_bound而使用尺取法

    可以降低复杂度,复杂度是(logn)*n,时间只有300多ms

    int ok(int  x)
    {
        int  cnt=0;
        for(int i=1,j=1;i<=n;i++)
              {
                  while(a[j]-a[i]<x&&j<=n)
                     j++;
                  cnt+=(j-1-i);
              }
        return cnt>=m;
    }
    

      

  • 相关阅读:
    Kafka日志及Topic数据清理
    python
    kotlin集合操作
    tomcat 下配置 可 调试
    linux 安装nexus3
    启动 idea 编译报错 kotlin
    nginx 增加 lua模块
    logstash配合filebeat监控tomcat日志
    redis 高级特性 不要太好用
    SpringBoot与Docker1
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5123626.html
Copyright © 2020-2023  润新知