POJ3579 Median

Posted yu-xing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3579 Median相关的知识,希望对你有一定的参考价值。

  • 题意:给出N个数,对于存有每两个数的差值的序列求中位数(一共(C_n^2)个),如果这个序列有偶数个元素,就取中间偏小的作为中位数。

  • 思路:

注意到题目中对于每两个数求差值,所有数的排列顺序不影响结果,所以可以先对数组排序。

因为答案具有单调性,所以可以二分答案ans,check函数中求出差值小于等于ans的数对数量cnt,与总方案数(差值序列元素个数)的二分之一比较(中位数),更改ans的上下界。

这里可以枚举每个(a_i) ,统计小于等于(a_i+ans) 的数有多少个,计入cnt变量中。

具体方法:枚举 a[i],?然后二分 i之后的区间,假设a[j]是最后一个小于等于a[i]+ans的值,那么cnt加上j-i的值。

时间复杂度:O((nlog^2n))

优化:依题意,数组中均为非负整数,可利用单调性,用i和j双指针进行优化。

时间复杂度:O((nlogn))

  • 其他
    1. (C_n^2=n*(n-1)/2);
    2. check函数中注意原序列中元素个数为奇数还是偶数,若是偶数,依题意答案向下取,判断时不加等号。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100005,INF=0x3f3f3f3f;
int n,a[maxn];
bool check(int x){
    int cnt=0;
    for(int i=1,j=1;i<=n;++i){
        while(a[j]<=a[i]+x&&j<=n) ++j;
        --j;
        cnt+=j-i;
    }
    if(!(((n*(n-1))>>1)&1)) return cnt < (n*(n-1))>>2;
    else return cnt <= (n*(n-1))>>2;
}
int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        int l=0,r=INF;
        while(l<r){
            int mid=l+r>>1;
            if(check(mid)) l=mid+1;
            else r=mid;
        }
        printf("%d
",l);
    }
    return 0;
} 

以上是关于POJ3579 Median的主要内容,如果未能解决你的问题,请参考以下文章

POJ3579 Median

POJ3579 Median

POJ 3579 Median 二分+思维

POJ 3579 Median

POJ 3579 Median(二分答案+Two pointers)

POJ - 3579 Median(二分)