首页 > 代码库 > poj 3579 Median
poj 3579 Median
Median
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. Output For each test case, output the median in a separate line. Sample Input 41 3 2 431 10 2 Sample Output 18 Source POJ Founder Monthly Contest – 2008.04.13, Lei Tao |
题意:给出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 10000110 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 }
poj 3579 Median