zoukankan      html  css  js  c++  java
  • POJ 3579 Median 【二分答案】

    <题目链接>

    题目大意:

    给出 N个数,对于存有每两个数的差值的序列求中位数,如果这个序列长度为偶数个元素,就取中间偏小的作为中位数。

    解题分析:

    由于本题n达到了1e5,所以将这些数之间的差值全部求出来显然是不可行的,这里用的是二分答案。先通过二分,假设枚举出的答案为mid,即,这些数字差值绝对值的中位数为mid。然后我们在通过二分查找,对每一个数字,查找它后面的所有满足与它的差值小于等于mid的数的个数,即查找所有差值小于等于mid的对数。因为中位数所在的编号很容易求得,为 (n*(n-1)/2+1)/2(因为总共有n*(n-1)个差值,题目说了∣Xi - Xj∣ (1 ≤ i  j  N) )。然后将得到的差值小于等于mid 的对数与mid 的坐标相比较,从而判断该答案的对错。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int M =1e5+5;
    typedef long long ll;
    int n;
    ll arr[M],res;
    
    bool juge(ll x){
    	ll sum=0;
    	for(int i=1;i<=n;i++)
    		sum+=lower_bound(arr+i,arr+1+n,arr[i]+x+1)-(arr+i)-1;    //这是用于查找小于等于arr[i]+x的数的个数,即与arr[i]绝对值之差小于等于x的数的对数 
    	return sum>=res;  //如果大于等于理论值 
    }
    
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		for(int i=1;i<=n;i++)
    			scanf("%lld",&arr[i]);
    		sort(arr+1,arr+n+1);
    		res=(n*(n-1)/2+1)/2;   //小于等于差值中位数的对数     
    		ll l=0,r=arr[n]-arr[1];  //差值最大为arr[n]-arr[1] 
    		while(l<r){
    			ll mid=(l+r)>>1;
    			if(juge(mid))r=mid;
    			else l=mid+1;
    		}
    		printf("%lld
    ",l);
    	}
    	return 0;
    }
    

     

    2018-09-20

  • 相关阅读:
    git
    浏览器喧嚷过程
    B/S架构与C/S架构
    simpleDateFormat
    oracle中case when的用法
    Java程序利用Jdbc连接数据库
    List 和 Set与Map
    队列和栈
    toString方法分析
    java中的构造器
  • 原文地址:https://www.cnblogs.com/00isok/p/9683030.html
Copyright © 2011-2022 走看看