poj 3579

/*

    描述:
        给定n个数字,求所有两两数字之差的绝对值的中位数。
        可知,共有n*(n-1)/2=m个数字。

    解析:
        因为满足性质——假如对key可以找出>m/2个数字>=key,那么对于任意key',
        有 key' <= key -> key'亦满足性质
        所以利用这个性质进行二分答案

        ans是最终答案,也是最后一个满足性质的数字
        对val,如果满足性质,那么val<=ans,否则val>ans

        从0到最大值是范围。(left,right)
        test(val)——可以找出来>m/2个数字>=val(因为必须包含val自身,所以必然>m/2)
            ——假如可以,那么答案在集合[val,right)中
            ——不可以,说明目前val过大了,答案在集合(left,val)中

        test(val)
        range(c,1,n)
        {
            ans += n - (lower_bound(a,a+n,a[c]+val)-a);
            //找到第一个和目前差值>-=val的,计算总共有多少个这样的数字
        }
        return ans > m/2;
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#define range(i,a,b) for (int i=a;i<=b;i++)

using namespace std;

const int maxn = 100000;

int a[maxn+1];
int n;
int m;

bool test(int val)
{
    int ans(0);
    range(c,0,n-1)
    {
        ans += n - (lower_bound(a,a+n,a[c]+val) - a);
    }
    return ans > m;
}

void Work(int n)
{
    m = (n-1)*n/4;
    range(i,0,n-1)
    {
        scanf("%d",&a[i]);
    }

    sort(a,a+n);

    int l(0),r(a[n-1]-a[0]);//注意r的初始化,直接为a[n-1]有点大

    while(l+1<r)//必须如此,不然超时
    {
        int mid = (l+r)>>1;
        if (test(mid))
        {
            l = mid;
        }
        else
        {
            r = mid;
        }
    }
    if (test(r))
    {
        cout<<r<<endl;
    }
    else
    {
        cout<<l<<endl;
    }
}

int main()
{
    while(cin>>n)
    {
        Work(n);
    }


    return 0;
}
原文地址:https://www.cnblogs.com/dandi/p/4075343.html