poj 3579 Median

Median
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3882   Accepted: 1139

Description

Given N numbers, X1X2, ... , 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 = 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 X1X2, ... , XN, ( X≤ 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

Source

题意:给出n(3<=n<=100000)个数,f(i,j)=|a[i]-a[j]| (1<=i<j<=n)。求所有的f(i,j)里面中位数的值。

思路:虽然题目要求i<j,但我们注意到最后还要求一个绝对值,所以|a[i]-a[j]|==|a[j]-a[i]|,所以其实就是n个数中找一对数,大数减小数。这时答案就很明显了,先把数列排序,然后二分答案x,再查找是否有(n*(n-1)/2+1)/2个小于等于x的f[i][j]来判断二分的答案。 查找的过程使用二分查找,所以一共使用两个二分。

 1 /*
 2  * Author:  Joshua
 3  * Created Time:  2014年10月07日 星期二 21时39分08秒
 4  * File Name: poj3579.cpp
 5  */
 6 #include<cstdio>
 7 #include<algorithm>
 8 using namespace std;
 9 #define maxn 100001
10 int n,a[maxn];
11 typedef long long LL;
12 LL limit;
13 
14 int find(int x,int y)
15 {
16     int left=1,right=y,mid;
17     while (left<right)
18     {
19         mid=(left+right)>>1;
20         if (a[mid]<x) left=mid+1;
21         else right=mid;
22     }
23     return left;
24 }
25 
26 bool check(int x)
27 {
28     LL sum=0;    
29     for (int i=1;i<=n;++i)
30     {
31         sum+=(LL)i-find(a[i]-x,i);
32         if (sum>=limit) return true;
33     }
34     return false;
35 }
36 void solve()
37 {
38     int left=0,right=0x7fffffff,mid;
39     for (int i=1;i<=n;++i)
40         scanf("%d",&a[i]);
41     limit=(LL)n*(n-1)/2;
42     limit=(limit+1)/2;
43     sort(a+1,a+n+1);
44     while (left<right)
45     {
46         mid=(left+right)>>1;
47         if (!check(mid)) left=mid+1;
48         else right=mid;
49     }
50     printf("%d\n",left);    
51 }
52 int main()
53 {
54     while (scanf("%d",&n)>0)
55         solve();
56     return 0;
57 }

 

posted @ 2014-10-08 00:17  一个大叔  阅读(1310)  评论(1编辑  收藏  举报