题意:
给n个数字组成的序列,求| Xi - Xj | ( 0 <= i < j < n) 的中位数是多少。
n(100000),X(1000000000)。
解析:
n灰常大,所以普通枚举不行。
所以先二分中位数是多少。
然后将X排个序,然后可以二分出比(mi + Xi)大的数有多少个,代表了差值中比中位数大的数有多少个。
然后若个数 < C(n, 2), 说明比中位数大的数少了,说明中位数太大了。
二分15次就可以得到答案了,50次的话差不多TLE那样。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
int n;
LL x[maxn];
LL d;
bool ok(LL mi)
{
LL cnt = 0;
for (int i = 0; i < n; i++)
{
cnt += n - (lower_bound(x + i, x + n, x[i] + mi) - x);
}
return cnt <= d / 2;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (~scanf("%d", &n))
{
LL lo = 0, hi = 0;
for (int i = 0; i < n; i++)
{
scanf("%lld", &x[i]);
hi = hi < x[i] ? x[i] : hi;
}
sort(x, x + n);
d = (n * (n - 1)) >> 1;
for (int i = 0; i < 15; i++)
{
LL mi = (lo + hi) >> 1;
if (ok(mi))
hi = mi;
else
lo = mi;
}
printf("%lld\n", lo);
}
return 0;
}