题目大意

给定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 二分法的更多相关文章

  1. C语言两种查找方式(分块查找,二分法)

    二分法(必须要保证数据是有序排列的):   分块查找(数据有如下特点:块间有序,块内无序):    

  2. poj3122-Pie(二分法+贪心思想)

    一,题意: 有f+1个人(包括自己),n块披萨pie,给你每块pie的半径,要你公平的把尽可能多的pie分给每一个人 而且每个人得到的pie来自一个pie,不能拼凑,多余的边角丢掉.二,思路: 1,输 ...

  3. 二分法&三分法

    ural History Exam    二分 #include <iostream> #include <cstdlib> using namespace std; //二分 ...

  4. [No000087]Linq排序,SortedList排序,二分法排序性能比较

    using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; ...

  5. [PHP]基本排序(冒泡排序、快速排序、选择排序、插入排序、二分法排序)

    冒泡排序: function bubbleSort($array){ $len=count($array); //该层循环控制 需要冒泡的轮数 for($i=1;$i<$len;$i++){ / ...

  6. iOS常见算法(二分法 冒泡 选择 快排)

    二分法: 平均时间复杂度:O(log2n) int halfFuntion(int a[], int length, int number)  { int start = 0; int end = l ...

  7. java简单的二分法排序

    二分法排序的思路:数据元素要按顺序排列,对于给定值 x,从序列的中间位置开始比较,如果当前位置值等于 x,则查找成功:若 x 小于当前位置值,则在数列的前半段中查找:若 x 大于当前位置值则在数列的后 ...

  8. 使用二分法查找mobile文件中区号归属地

    #!/usr/bin/env python #coding:utf-8 ''' Created on 2015年12月8日 @author: DL @Description: 使用二分法查找mobil ...

  9. Atitit 迭代法  “二分法”和“牛顿迭代法 attilax总结

    Atitit 迭代法  "二分法"和"牛顿迭代法 attilax总结 1.1. ."二分法"和"牛顿迭代法"属于近似迭代法1 1. ...

随机推荐

  1. 【Unity/Kinect】获取预制的手势信息KinectInterop.HandState

    Kinect使用了枚举KinectInterop.HandState来描述手势. 该手势指的是手掌的状态(张开/握拳),而不是说整个手臂的肢体动作(Gesture). 同样是需要嵌套在Kinect获取 ...

  2. [pthread]Linux C 多线程简单示例

    #include <stdio.h> #include <pthread.h> pthread_mutex_t mutex; pthread_cond_t cond; void ...

  3. MongoDB之分片

    本文介绍分片的思想和MongoDB中的实现方法. 首先须要介绍一些主要的概念. 分片 分片.也叫做分区.是一种经常使用的数据库优化技术.其含义就是将数据拆分,将数据分散到不同机器上的过程.这样就能够使 ...

  4. Python写自己主动化之邮件发送(匿名)

    为了可以实现邮件发送功能.首先.我们须要了解一下邮件的发送过程是什么样子的,此处不再具体说明,请大家自行搜索或查看p=438">http://www.sogouqa.com/?p=43 ...

  5. nodejs系列笔记02---模块路径解析

    模块路径解析规则 参考这篇博客 我们已经知道,require函数支持斜杠(/)或盘符(C:)开头的绝对路径,也支持./开头的相对路径.但这两种路径在模块之间建立了强耦合关系,一旦某个模块文件的存放位置 ...

  6. Applet Mode

    https://github.com/threerings/getdown/wiki/Applet-Mode ————————————————————————————————————————————— ...

  7. 判断radiobutton是否被选中

    <tr> <td class="label">是否显示:</td> <td> <?php if($cates_data[0][ ...

  8. Windows消息目录

    Windows消息目录1. WM_NULL=$0000:2. WM_CREATE=$0001: 应用程序创建一个窗口3. WM_DESTROY=$0002: 一个窗口被销毁4. WM_MOVE=$00 ...

  9. 受打击了:你是学.net 的吧?

    我在网上投了简历,今天去面试, 去到才知道有面试题做,做完之后自知答的很烂. 没想到面试我的那个人,一开始就很直接,说: 我感觉你很喜欢用英语, 但英语很烂 我觉得你很喜欢用别人的东西, 但技术水平很 ...

  10. WCF(二)

    摘自:http://www.cnblogs.com/yank/p/3666271.html WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK ...