Median POJ3579

投稿日: 更新日:

問題:http://poj.org/problem?id=3579

問題

NN個の数X1,X2,...,XNX_1,X_2,...,X_Nが与えられます。この中から2つ選びその絶対値の差XiXj(1i<jN)|X_i - X_j|(1\leqq i < j \leqq N)を求めます。全部でNCK{}_NC_K個あるのでその中央値を求めてください。もし、偶数個の場合はm/2m/2番目の数を求めてください

解法

XiXjv|X_i - X_j| \geqq vを満たす組み合わせは何個あるかで2分探索をします。

あらかじめ数列をソートしておきます。iiを固定したとき、XjXi+vX_j \geqq X_i+vが成り立つXjX_jを2分探索で求めれば個数がすぐに求まります。実装ではlower_boundを使用しています。

実装

cincoutを使うとTLEしました。scanfprintfを使って922MSだったのでギリギリです。厳しい。。。。

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        vector<int> a(n);
        for(int i = 0;i < n; ++i){
            scanf("%d", &a[i]);
        }

        sort(a.begin(), a.end());

        long long med = 1LL*n*(n-1)/4+1;

        int ng = 1e9+10, ok = 0;
        while(ng - ok > 1){
            int mid = (ok+ng)/2;

            long long count = 0;
            for(int i = 0;i < n; ++i){
                count += a.end() - lower_bound(a.begin()+i+1, a.end(), a[i]+mid);
            }

            if(count >= med){
                ok = mid;
            }else{
                ng = mid;
            }
        }

        printf("%d\n", ok);
    }
    return 0;
}

書いた人

profile_image

お茶の葉

物理とプログラミングが好きな人