zoukankan      html  css  js  c++  java
  • POJ3579 Median

    • 题意:给出N个数,对于存有每两个数的差值的序列求中位数(一共(C_n^2)个),如果这个序列有偶数个元素,就取中间偏小的作为中位数。

    • 思路:

    注意到题目中对于每两个数求差值,所有数的排列顺序不影响结果,所以可以先对数组排序。

    因为答案具有单调性,所以可以二分答案ans,check函数中求出差值小于等于ans的数对数量cnt,与总方案数(差值序列元素个数)的二分之一比较(中位数),更改ans的上下界。

    这里可以枚举每个(a_i) ,统计小于等于(a_i+ans) 的数有多少个,计入cnt变量中。

    具体方法:枚举 a[i], 然后二分 i之后的区间,假设a[j]是最后一个小于等于a[i]+ans的值,那么cnt加上j-i的值。

    时间复杂度:O((nlog^2n))

    优化:依题意,数组中均为非负整数,可利用单调性,用i和j双指针进行优化。

    时间复杂度:O((nlogn))

    • 其他
      1. (C_n^2=n*(n-1)/2);
      2. check函数中注意原序列中元素个数为奇数还是偶数,若是偶数,依题意答案向下取,判断时不加等号。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=100005,INF=0x3f3f3f3f;
    int n,a[maxn];
    bool check(int x){
    	int cnt=0;
    	for(int i=1,j=1;i<=n;++i){
    		while(a[j]<=a[i]+x&&j<=n) ++j;
    		--j;
    		cnt+=j-i;
    	}
    	if(!(((n*(n-1))>>1)&1)) return cnt < (n*(n-1))>>2;
    	else return cnt <= (n*(n-1))>>2;
    }
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    		sort(a+1,a+1+n);
    		int l=0,r=INF;
    		while(l<r){
    			int mid=l+r>>1;
    			if(check(mid)) l=mid+1;
    			else r=mid;
    		}
    		printf("%d
    ",l);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    如何使用Java、Servlet创建二维码
    Java线程池主线程等待子线程执行完成
    Java多线程--让主线程等待所有子线程执行完毕
    查询及删除重复记录的方法
    聚集索引和非聚集索引
    数据库索引类型及实现方式
    各种排序算法的分析及java实现
    两个变量交换值的方法
    Java性能优化技巧
    JVM调优总结(九)-新一代的垃圾回收算法
  • 原文地址:https://www.cnblogs.com/yu-xing/p/10360672.html
Copyright © 2011-2022 走看看