zoukankan      html  css  js  c++  java
  • POJ:3579-Median(二分+尺取寻找中位数)

    Median

    Time Limit: 1000MS Memory Limit: 65536K
    Total Submissions: 9201 Accepted: 3209

    Description

    Given N numbers, X1, X2, … , 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 m = 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 X1, X2, … , XN, ( Xi ≤ 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


    中文题意:

    给N数字, X1, X2, … , XN,我们计算每对数字之间的差值:∣Xi - Xj∣ (1 ≤ i < j ≤ N). 我们能得到 C(N,2) 个差值,现在我们想得到这些差值之间的中位数。

    如果一共有m个差值且m是偶数,那么我们规定中位数是第(m/2)小的差值。

    输入包含多测
    每个测试点中,第一行有一个NThen N 表示数字的数量。
    接下来一行由N个数字:X1, X2, … , XN
    ( Xi ≤ 1,000,000,000 3 ≤ N ≤ 1,00,000 )


    解题心得:

    1. 首先要知道的是n个数字可以得到C(N,2)个数字,那么要得到中位数,如果是偶数就要得到第n/2大的数字,如果是奇数就要得到第n/2+1个数字。
    2. 具体做法可以先将给出的数字排序,然后每次二分枚举一个中位数(O(logn)),然后验证比这个中位数小的数字有多少个,在验证比这个中位数小的数字有多少个的时候可以选择尺取法(具体实现看代码,O(n)),这样就在O(nlogn)的复杂度内完成。

    #include <algorithm>
    #include <stdio.h>
    #include <cstring>
    using namespace std;
    const int maxn = 1e5+100;
    
    int n,num[maxn];
    long long tot;
    
    void init() {
        tot = 0;
        tot = (long long)n*(n-1)/2;//差值的个数
        if(tot%2 == 0) {//中位数在第几个
            tot /=2;
        }
        else
            tot = tot/2 + 1;
        for(int i=0;i<n;i++) {
            scanf("%d",&num[i]);
        }
        sort(num,num+n);
    }
    
    bool checke(int va) {
        int t = 0;
        long long sum = 0;
        for(int i=0;i<n;i++) {
            while(t < n && num[t] - num[i] <= va)//尺取法看比va小的值有多少个
                t++;
            sum += t-i-1;
        }
        if(sum < tot)
            return true;
        return false;
    }
    
    int binary_search() {//每次枚举一个中位数的值
        int l,r;
        l = 0, r = 1e9+100;
        while(r - l > 1) {
            int mid = (l + r) >> 1;
            if(checke(mid))
                l = mid;
            else
                r = mid;
        }
        return r;
    }
    
    int main() {
        while(scanf("%d",&n ) != EOF) {
            init();
            int ans = binary_search();
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    python连接字符串的几种方法--转子(香草拿铁的园子)
    winform属性
    C# Timer
    SQL基础
    SQL 基础
    File类 ReadAllBytes() ReadAllLines() ReadAllText()
    学习C#20天有感
    装箱和拆箱
    机器学习基础:朴素贝叶斯小结
    分类问题样本不均衡问题
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9107120.html
Copyright © 2011-2022 走看看