题目来源:http://poj.org/problem?id=3579
二分答案+尺取。
首先想到要对数列进行排序。
先二分差值的中位数x,然后找出小于x的所有差值的个数以及所有大于x的差值的个数,这个过程可以用尺取法。
同时统计出差值=x的差值个数t。若t=0,则这个mid不可能是答案。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n;
ll a[maxn];
ll up(ll x)
{
ll tot=0;
int r=2;
for(int l=1;l<=n;++l)
{
while(r<=n&&a[r]-a[l]<=x)
r++;
if(r>n)break;
tot+=n-r+1;
}
return tot;
}
ll down(ll x)
{
int tot=0;
int l=1;
for(int r=2;r<=n;++r)
{
while(l<r&&a[r]-a[l]>=x)
++l;
tot+=r-l;
}
return tot;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]);
sort(a+1,a+1+n);
ll tot=n*(n-1)/2;
ll l=0,r=a[n];
ll ans=0;
ll m=(tot+1)/2;
while(l<=r)
{
ll mid=(l+r)/2;
ll u=up(mid),d=down(mid);
ll t=tot-u-d;
if(t==0)
{
if(d>=m)r=mid-1;
else l=mid+1;
continue;
}
if(d<m)
{
if(d+t>=m)
{
ans=mid;
break;
}
else l=mid+1;
}
else r=mid-1;
}
printf("%lld\n",ans);
}
return 0;
}