给了N个数字,
X
1
…
X
n
X_1\dots X_n
X1…Xn对于每对数字的差值
∣
X
i
−
X
j
∣
|X_i-X_j|
∣Xi−Xj∣,找出这些差值的中位数
思路
用的是双重二分
我们取最大的元素减去最小的元素作为二分答案开始查找,第一重二分查找,遍历这个数组
对于数组的每个元素来说(数组已经排好序了),如果我们发现,这个二分答案大于这个最大值减去当前值
a
[
n
−
1
]
−
a
[
i
]
a[n-1]-a[i]
a[n−1]−a[i],那么说明当前的二分答案小了,所以直接停掉这个遍历就行了(因为后面的比
a
[
i
]
a[i]
a[i]大更不会符合这个条件)
#include<iostream>#include<algorithm>usingnamespace std;constint N =1e5+10;int a[N], sum =0, n , k;intcal(int x){int l =0, r = n;while(l < r){int mid =(l + r)>>1;if(x < a[mid]){
r = mid;}else{
l = mid +1;}}//查找第一个大于等于key的位置return n - r;}boolcheck(int x){for(int i =0; i < n ; i++){if(a[i]+ x > a[n -1])break;
sum +=cal(a[i]+ x);}if(sum <= k)returntrue;returnfalse;}intmain(){while(scanf("%d",&n)!=EOF&&n){for(int i =0; i < n ; i++){scanf("%d",&a[i]);}sort(a,a+n);
k =(n -1)*n/4;//排列次数的中位数int l =0, r = a[n -1]- a[0];//以 0 和差的最大值二分答案while(l < r){int mid =(l + r)>>1;if(check(mid)){
r = mid;}else{
l = mid +1;}
sum =0;}printf("%d\n",r);}}