这题也是二分,但有很多特殊的地方:
题意是输入一串数,这些数之间的差排成一列,找出其中的中位数第一次二分枚举猜测中位数为mid,比较a[i]+mid与后面的数,与m比较确定区间,第二次二分是在比较的过程中,如果用两个迭代还是N^2,所以用二分求上界,总数减去返回的下标值就是后面大于或等于a[i]+mid的数量。
这题有个奇怪的地方,说是第m/2个最小值为中位数但如1,2,10的差是1,8,9,中位数是8,但m=1。
而且这题step=mid必须放到sum>m后,也就是说中位数时sum只大于m,不包括等于m的情况,可以写几个数据验证一下,题目给的第一组数据就可以看出来,以后做这种题这些地方最好还是验证一下
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 100000+100
int a[maxn], n,m;
int cmp(const void*a, const void*b)
{
return *(int*)a - *(int*)b;
}
int lower_bound(int left, int right, int v)//二分求上界
{
int m;
while (left < right)
{
m = (left + right) / 2;
if (a[m] >= v)
right = m;
else
left = m + 1;
}
return left;
}
bool test(int mid)
{
int i,sum=0;
for (i = 0; i < n; i++)
{
sum += n - lower_bound(i,n,a[i]+mid);//再次二分减少时间
}
if (sum > m) //大于说明mid开小了
return true;
else
return false;
}
int main()
{
while (scanf("%d", &n) != EOF)
{
int left = 0, right = 0, mid,step;
int i;
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
qsort(a, n, sizeof(a[0]), cmp);
m = n*(n - 1) / 4;
right = a[n - 1] - a[0];
while (left <= right)
{
mid = (left + right) / 2;
if (test(mid))
{
step = mid; //注意这步一定要放这里,可以找几个例子推一下
left = mid + 1;
}
else
{
right = mid - 1;
}
}
printf("%d\n", step);
}
return 0;
}