UESTC_基爷的中位数 2015 UESTC Training for Search Algorithm & String<Problem D>

D - 基爷的中位数

Time Limit: 5000/3000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

给你N个数,X1,X2,...,XN, 基爷让我们计算任意两个数差的绝对值 XiXj (1i<jN) 。 这样,我们可以得到 C2N 个数。

现在,基爷希望聪明的你能用一个简单的程序求出这 C2N 个数的中位数!

Input

输入有多组数据。

每组数据,第一行一个整数 N,第二行给出 N 个整数 X1,X2,...,XN ( |Xi|1,000,000,0003N100,000 )

Output

按要求输出中位数,每个数占一行。

Sample input and output

Sample InputSample Output
4
1 3 2 4
3
1 10 2
1
8

Hint

当这 C2N 个数的个数为偶数 M 的时候,取第 M2 个最小的数作为中位数 ( 别问为什么,这就是基爷的中位数! )

解题报告:

 排序之后二分答案,每次找位置也是二分,总复杂度 olognlogx,每次找严格小于这个数的数有多少个!!

 总之。。注意细节(我挂了35发)

#include <iostream>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1e5 + 50;
ll x[maxn];
ll n;


int main(int argc,char *argv[])
{
  while(~scanf("%lld",&n))
   {
         for(int i = 0 ; i < n ; ++ i) scanf("%lld",&x[i]);
         sort(x,x+n);
         ll r = 5e9 ,  l= -5e9;
         ll tar = n*(n-1)/2;
         if (tar & 1)
          tar /= 2;
         else
          tar = tar / 2 - 1;
         //小于等于目标位置的有多少个数 
         while(r > l)
          {
                ll mid = l + (r-l + 1) / 2;
             ll rank = 0;
             for(int i = 0 ; i < n - 1 ; ++ i)
              rank += (lower_bound(x+i+1,x+n,mid+x[i])-(x+i+1)); // 小于该数的有几个 
             if (rank > tar)
              r = mid - 1;
             else
              l = mid;
       }
      printf("%lld
",r);
   }
  return 0;
}
No Pain , No Gain.
原文地址:https://www.cnblogs.com/Xiper/p/4497066.html