http://poj.org/problem?id=3579
题意:给出N个数字, 求∣Xi - Xj∣ (1 ≤ i < j ≤ N) 的中位数。
( Xi ≤ 1,000,000,000 3 ≤ N ≤ 1,00,000 )
——————————————————
如果先将所有的∣Xi - Xj∣求出来找到中位数的话,但是计算出C(N,2)个∣Xi - Xj∣就会超时了。
二分搜索法:
先将a[]排序,然后二分搜索差值(答案),再通过二分搜索进行判断。O(log(MAX_X)*N*log(N))。
C():
a+N - lower_bound(a, a+N, a[i]+x) 算出比a[i]大于或等于x的个数cnt。
如果一旦cnt == 0,因为a[]是递增的,那么后面的也是cnt == 0,可以直接跳出。
如果cnt>m说明差值x是比较大的,应该搜索小区间。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N = 1e5;
int a[MAX_N];
int N, m;
bool C(int x)
{
int cnt = 0;
for(int i = 0; i < N; i++)
{
cnt += a+N - lower_bound(a, a+N, a[i]+x);
if(cnt == 0) break;
}
return cnt > m;
}
void solve()
{
m = N*(N-1)/4;
sort(a, a+N);
int l = 0, r = a[N-1] - a[0];
while(r - l > 1)
{
int mid = (l + r) / 2;
if(C(mid))
l = mid;
else
r = mid;
}
printf("%d\n", l);
}
int main()
{
//freopen("in.txt", "r", stdin);
while(scanf("%d", &N) != EOF)
{
for(int i = 0; i < N; i++)
scanf("%d", a+i);
solve();
}
return 0;
}