POJ - 3579 Median

二分中间值x,x和大于等于x的值的数量cnt具有单调性,随着x增大,满足cntx <cntmid:111000。

中间值是满足条件最右边的一个。(所以是≤)

统计cnt。因为是取了绝对值,和Xi和Xj选取顺序没有关系,如果把X序列排序以后,枚举小的Xi,那么X[j] - X[i] ≥ x

找到满足条件最小的Xjmin,后面的都满足条件,Xi增大,Xjmin也是单调的,尺取就好。

/*********************************************************
*            ------------------                          *
*   author AbyssalFish                                   *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include<numeric>
using namespace std;

const int MAX_N = 1e5;
int N;
int X[MAX_N];
long long r_med;


bool P(int x) //x>0
{
    long long cnt = 0;
    for(int i = 0, j = 1; i < N-1; i++){
        while(j < N && X[i]+x > X[j]) j++;
        //if(i>=j) j++;
        cnt += N-j;
    }
    return cnt >= r_med;
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    while(~scanf("%d",&N)){
        for(int i = 0; i < N; i++) scanf("%d",X+i);
        sort(X,X+N);
        long long tot = ((N*(N-1LL))>>1);
        r_med = tot-((tot-1)>>1);
        int lb = 0, ub = X[N-1]-X[0], md;
        while(lb < ub){
            md = (lb+ub+1)>>1;
            P(md) ? lb = md : ub = md-1;
        }
        printf("%d\n",lb);
    }
    return 0;
}

 

posted @ 2015-11-19 13:32  陈瑞宇  阅读(214)  评论(0编辑  收藏  举报