Median
Time Limit: 1000MS         Memory Limit: 65536K
Total Submissions: 3699         Accepted: 1056
Description

Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i < j ≤ N). We can get C(N,2) differences through this work, and now your task is to find the median of the differences as quickly as you can!

Note in this problem, the median is defined as the (m/2)-th  smallest number if m,the amount of the differences, is even. For example, you have to find the third smallest one in the case of m = 6.

Input

The input consists of several test cases.
In each test case, N will be given in the first line. Then N numbers are given, representing X1, X2, ... , XN, ( Xi ≤ 1,000,000,000  3 ≤ N ≤ 1,00,000 )

Output

For each test case, output the median in a separate line.

Sample Input

4
1 3 2 4
3
1 10 2
Sample Output

1
8

题意:找到所有数两者差的集合中和第k小的数根,据题目意思k为(C(N,2)+1)/2,因为如果不能整除的话要+1再除以2。

分析:首先平常算法肯定会超时,这时候就需要枚举答案ans,首先对数据a排序,ans上下界范围0~a[n]-a[1],我们二分枚举它找到第一个>=k的ans,然后二分函数中再来一个二分找到a[i+1~n]中<=a[i]+mid的个数,我们找到a[i+1~n]中<=a[i]+mid的最大位置pos,sum(pos-i)即为差值<=ans的个数。

 

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) throws IOException {
Scanner in = new Scanner (new BufferedInputStream(System.in));
//Scanner in = new Scanner(new BufferedInputStream(System.in));
Reader.init(System.in);
while(in.hasNext())
{
int n=in.nextInt();

int [] a=new int[n+1];
for(int i=1;i<=n;i++)
a[i]=in.nextInt();
Arrays.sort(a,1,n+1);
int k=n*(n-1)/2;
if(k%2==1) k=(k+1)>>1;
else k=(k>>1);
int l=0,r=a[n]-a[1]+1;
//System.out.println(r);
while(l<r)
{
int mid=(l+r)>>1;
if(f(a,mid,n)>=k)
r=mid;
else
l=mid+1;
}
System.out.println(l);
}
}

private static int f(int[] a, int key,int n) {
// TODO 自动生成的方法存根
int sum=0;
for(int i=1;i<=n;i++)
{
int l=i,r=n;
while(l<r)
{
int mid=(l+r+1)>>1;
if(a[mid]<=a[i]+key)
l=mid;
else
r=mid-1;
}

//System.out.println( i+" "+l+" "+key+" "+a[i]);
sum+=l-i;

}
//System.out.println(sum);
return sum;
}


}
class Reader
{
static BufferedReader reader;
static StringTokenizer tokenizer;

static void init(InputStream input)
{
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}

static String next() throws IOException
{
while(!tokenizer.hasMoreTokens())
{
String str=reader.readLine();
//System.out.println(str);
tokenizer = new StringTokenizer(str);
}
return tokenizer.nextToken();
}

static int nextInt() throws IOException
{
return Integer.parseInt(next());
}

static double nextDouble() throws IOException
{
return Double.parseDouble(next());

}
}