zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    IIS文件大小限制
    XAMPP 配置多端口 多站点
    C# 复制文件和文件夹
    Windows下 Python 安装包的配置
    从数据库读取数据绑定到TreeView(内含设置样式,图片)
    异步请求数据简单例子
    Jmeter使用_StringFromFile函数需要添加编码方式
    利用Fitnesse和Jmeter实现接口性能测试
    简易覆盖率信息收集框架
    如何对遗留代码进行单元测试(scrumgathering听后感)
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5123626.html
Copyright © 2011-2022 走看看