首页 > 代码库 > poj 3579

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;}

 

poj 3579