POJ3579 Median(二分答案 + O(N)判定)

来源:互联网 发布:seo推广是什么 编辑:程序博客网 时间:2024/05/17 08:16

出处:http://blog.csdn.net/gengmingrui/article/details/47671265

传送门 

大意:给出N个数,对于存有每两个数的差值的序列求中位数,如果这个序列有偶数个元素,就取中间偏小的作为中位数。

因为N<=100000,所以想要求出每一个差值是不可行的,我们很容易想到二分答案。 在二分答案时我们会进行判定,求出小于等于枚举值的个数,我看其他人的判定似乎都是O(NlogN) 的,我在这里就给出一个O(N)的判定方法。

首先同样将数组排序(我们命名为a数组好了) 
我们枚举一个区间[l,r),因为当r增加的时候,要使[l,r)中的数都大于于等于a[r]lrl,O(n)

上代码:

#include <cstdio>#include <algorithm>long long n, a[100005];int main(){    long long i, j;    while(~scanf("%I64d", &n))    {        for(i = 1; i <= n; i ++)            scanf("%I64d", a + i);        std::sort(a + 1, a + n + 1);        long long l = 0, r = a[n], mid, m = (n-1)*n/4, num;        if((n*(n-1)/2)&1) m ++;        if(n == 1)        {            printf("0\n");            continue;        }        while(l < r)        {            mid = (l + r) >> 1;            j = 1;            num = 0;            for(i = 2; i <= n; i ++)            {                while(a[i] - a[j] > mid)                    j ++;                num += (i-j);            }            if(num >= m)                r = mid;            else l = mid + 1;        }        printf("%I64d\n", l);    }    return 0;}