题意:给出N个数,求这个N个数的所有间隔中的中位数,如果有偶数个,则取中间两个中的前面那一个。
分析:因为N的取值最大为1E5,所以我们不能直接求出所有间隔来算。那么第一个想到的就是二分来做,因为间隔的取值范围我们可以得知,所以我们在这个范围内二分查找,对于每一个值,我们再通过O(n)的查找确定小于等于它的间隔数量有多少,将它与中位 (N∗(N−1)+1)/2 比较,找到大于等于它的最小间隔值,就是解。
AC代码:
/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
#include <climits>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 100001
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<<endl;
#define debug(x) cout << #x" = " << x << endl;
LL N;
LL X[MaxN];
map<LL,int> M;
LL check(LL x)
{
int r = 0;
LL cnt = 0;
for(int l=0;l<N;l++)
{
while( r<N && X[r]-X[l]<=x) r++;
cnt += (r-l-1);
}
return cnt;
}
int main()
{
//std::ios::sync_with_stdio(false);
while(~scanf("%lld", &N))
{
M.clear();
LL biao = N*(N-1)/2;
if(biao&1) biao = biao/2+1;
else biao = biao/2;
for(int i=0;i<N;i++)
{
scanf("%lld", &X[i]);
}
sort(X,X+N);
LL MAX = X[N-1] - X[0];
LL L = 1, R = MAX;
while(L<=R)
{
LL mid = (L+R)/2;
if( check(mid) >=biao) R = mid-1;
else L = mid+1;
}
printf("%lld\n", L);
}
}