• 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;
    }
    

      

  • 相关阅读:
    享受法国葡萄酒
    shell (bash) hot keys
    传统MapReduce框架
    【oracle】常用命令
    【转】商业J2EE中间件价值何在?
    【转】Linux(CentOS)服务器上安装Webmin
    【转】CentOS 5安装免费主机控制面板Webmin
    【源码】不规则矩形窗体的设计
    【转】虚拟机VirtualBox+Centos+NAT网络的配置过程
    【jsp】 config配置的关键字
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5123626.html
Copyright © 2020-2023  润新知