题目
题解思路
很显然不能直接求出ans数组,先将数组排序,因为是任意差值的绝对值,顺序并不影响,我们对答案进行枚举。ans数组大小为n*(n-1)/2 ,这是可以根据等差数列求和得到的。
答案需要介于符合大于一半的ans数组数到不符合的左右。
设枚举的答案为p
当我们排序完后,很容易枚举出p小于等于那些差值的数量和sum,利用二分函数就可以得到,不论奇数偶数都应该大于ans数组的一半,因为sum包含了p自己的值。
这里还有个有点玄学的问题。
关于二分出来的边界问题,如果验证出来要从下界更新且都为正整数,我们需要用t2-t2>1来退出二分
例如
1 2,mid为1符合答案,下界又更新为1,这样就无限循环了。
此时还不能对上界进行更改,保证上界不符合答案。(问就是验证边界改变了,玄学二分)
AC代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n,k;
long long a[100100];
bool che(long long p)
{
long long sum = 0 ;
for (int i = 1 ; i <= n ; i++ )
sum += n - (lower_bound(a+1,a+n+1,p + a[i])-a-1);
return sum > k ; //加上了自己
}
int main ()
{
while(~scanf("%lld",&n))
{
long long t1 = 0 , t2 ;
k = n*(n-1)/4;
for (int i = 1 ; i <= n ; i++ )
scanf("%lld",&a[i]);
sort(a+1,a+1+n);
t2 = a[n] - a[1] ;
while( t1 < t2 - 1)
{
long long mid = (t2-t1)/2+t1 ;
if ( che(mid) )
{
t1 = mid;
}else
t2 = mid ;
}
printf("%lld\n",t1);
}
return 0;
}