poj_3579 二分法
题目大意
给定N个数,这些数字两两求差构成C(N,2)(即N*(N-1)/2)个数值,求这C(N,2)个数的中位数。N <= 100000.
题目分析
根据数据规模N最大为100000,可知不能直接求每两个数的查找(O(N*N)复杂度),然后排序,再求中位数。考虑使用二分法查找满足要求的中位数:
先将原数组排序,然后假设数k为中位数,那么如果这N个数字构成的C(N,2)个差值中小于k的小于C(N,2)/2个,则k需要增加;如果小于等于k的数字大于等于C(N,2),那么k需要减少。最后求出的k是恰好满足C(N,2)个差值中小于等于k的数大于等于C(N,2)个,且差值中存在k 的最小值。
实现(c++)
#include<stdio.h>
#include<algorithm>
using namespace std;
#define MAX_N 100005 int an[MAX_N];
int DiffKLessThanHalf(int n, int k){
int sum = 0;
int max_pair = n*(n-1) / 2;
max_pair = max_pair / 2 + max_pair % 2; //小于等于中位数的最少个数
bool flag = false;
for (int i = 0; i < n - 1; i++){
int beg = i + 1, end = n;
while (beg < end){
int mid = (beg + end) / 2;
if (an[mid] - an[i] == k){ //差值中存在k,说明k可以做为中位数
flag = true;
}
if (an[mid] - an[i] <= k)
beg = mid + 1;
else
end = mid;
}
sum += (beg - i - 1); //和 an[i] 的差值小于等于k的个数 为 beg - i - 1
if (sum >= max_pair && flag)//小于等于k的个数 至少为C(N,2) 且 存在差值等于k,说明k可以作为一个中位数,
//但后续需要继续求满足这种条件的最小的k。直接返回
return 2;
}
if (sum < max_pair) //小于等于k的个数 小于 C(N,2),说明中位数 > k
return 0;
return 1;
} int main(){
int n; while (scanf("%d", &n) != EOF){
for (int i = 0; i < n; i++){
scanf("%d", &an[i]);
}
sort(an, an + n);
int beg = 0, end = an[n-1] - an[0] + 1;
int rr = 0;
while (beg < end){
int mid = (beg + end) / 2;
int result = DiffKLessThanHalf(n, mid);
if (result == 0)
beg = mid + 1;
else if (result == 1){
end = mid;
}
else{
end = mid;
rr = mid; //记录下一个可能的中位数值
}
}
printf("%d\n", rr);
}
return 0;
}
poj_3579 二分法的更多相关文章
- C语言两种查找方式(分块查找,二分法)
二分法(必须要保证数据是有序排列的): 分块查找(数据有如下特点:块间有序,块内无序):
- poj3122-Pie(二分法+贪心思想)
一,题意: 有f+1个人(包括自己),n块披萨pie,给你每块pie的半径,要你公平的把尽可能多的pie分给每一个人 而且每个人得到的pie来自一个pie,不能拼凑,多余的边角丢掉.二,思路: 1,输 ...
- 二分法&三分法
ural History Exam 二分 #include <iostream> #include <cstdlib> using namespace std; //二分 ...
- [No000087]Linq排序,SortedList排序,二分法排序性能比较
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; ...
- [PHP]基本排序(冒泡排序、快速排序、选择排序、插入排序、二分法排序)
冒泡排序: function bubbleSort($array){ $len=count($array); //该层循环控制 需要冒泡的轮数 for($i=1;$i<$len;$i++){ / ...
- iOS常见算法(二分法 冒泡 选择 快排)
二分法: 平均时间复杂度:O(log2n) int halfFuntion(int a[], int length, int number) { int start = 0; int end = l ...
- java简单的二分法排序
二分法排序的思路:数据元素要按顺序排列,对于给定值 x,从序列的中间位置开始比较,如果当前位置值等于 x,则查找成功:若 x 小于当前位置值,则在数列的前半段中查找:若 x 大于当前位置值则在数列的后 ...
- 使用二分法查找mobile文件中区号归属地
#!/usr/bin/env python #coding:utf-8 ''' Created on 2015年12月8日 @author: DL @Description: 使用二分法查找mobil ...
- Atitit 迭代法 “二分法”和“牛顿迭代法 attilax总结
Atitit 迭代法 "二分法"和"牛顿迭代法 attilax总结 1.1. ."二分法"和"牛顿迭代法"属于近似迭代法1 1. ...
随机推荐
- Entity Framework实体拆分
一.概念 实体拆分:一个实体拆分成多个表,如Product实体,可以拆分成Product和ProductWebInfo两个表,Product表用于存储商品的字符类信息,ProductWebInfo用于 ...
- 软件测试工具MonkeyTalk使用方法
1.简单介绍 MonkeyTalk软件测试工具由两部分构成:MonkeyTalk IDE 和 MonkeyTalk Agents MonkeyTalk IDE是Eclipse平台的工具,工能是:对iO ...
- 关于Cocos2d-x的数据存储
Cocos2d-x对数据的存储没有用到数据库,但是有用到一个类似数据库的小型数据库,就是数据存储.存储后的数据用XML的文件格式保存在C:\Users\Administrator\AppData\Lo ...
- Hibernate一级缓存、二级缓存以及查询缓存的关系
转载自http://blog.csdn.net/maoyeqiu/article/details/50209893 前两天总结了一下二级缓存和查询缓存的关系,但是又有一个新的问题,就是查询缓存缓存到二 ...
- Spring零散所得
Spring容器中bean的id或name,都可以有多个,且第一个为标识符(Qualifier),其余皆为别名(Alias).所以都可以通过applicationContext.getBean(&qu ...
- ConfigParser.NoSectionError: No section: 'MongoDB'
场景:手动执行bat文件正常,schtasks定时执行bat文件时报错. 原因:定时执行时,ini配置文件找不到.Windows 下用 schtasks 定时执行脚本的默认起始路径为:C:\Windo ...
- 不可在 for 循环体内修改循环变量,防止 for 循环失去控制
不可在 for 循环体内修改循环变量,防止 for 循环失去控制. #include <iostream> /* run this program using the console pa ...
- Sql server中根据存储过程中的部分信息查找存储过程名称的方法【视图和Function】
.查询的语句: select a.id,b.name,a.*,b.* from syscomments a join sysobjects b on a.id=b.id where b.xtype=' ...
- js 查找指定函数的内容
function test(){ //hahahhahahhahahha }alert(test.toString());
- 新兵训练营课程——环境与工具Java[转]
原文地址:http://weibo.com/p/1001643874239169320051 程序员在开发过程中会用到很多工具来提升开发和协作效率,这次介绍的是目前微博平台在开发过程中用到的一些工具, ...