poj-3579 Median
来源:互联网 发布:黑帮之地mac 编辑:程序博客网 时间:2024/04/28 11:05
题意给你n个数。两两相差的绝对值有c(n,2)个,有这c(n,2)个数的中位数
完全没法做啊有木有。。。完全没思路。。。
然后看了题解。。。
主题思路。。
细节理解。。。。
1.使用low_bound是为什么从a+i+1开始?
low_bound返回的是大于等于a[i]+val的第一个元素的地址。当val等于0时。返回的自身值的地址。这是不可取的。因为间隔的距离是不能与自身比较的。
2.(n-1)-(lower_bound(a+i+1,a+n,a[i]+val)-a)+1中为什么是n-1并且要+1?
(lower_bound(a+i+1,a+n,a[i]+val)-a)返回的是a数组的下标。下标的顶值是n-1,
加1,举个例子
0 1 2 3 4 5
2 3 5 8 9 10
假如a[i]+val=a[0]+val=2+1=3,那么返回的是1.n-5为5.5-1=4.而实际是4个元素,所以要加1.
3.right=*max_element(x,x+n)-*min_element(x,x+n)+1为什么要加1?
在c的判断函数中,if(sum > goal)是满足的,此时真值为left,这是为了避免极端情况当答案是一直向右二分,最后答案是right但是只能输出right-1,所以应该加1.
4.对中位数的表达中,为什么直接使用goal = n*(n-1)/4,然后在c的判断中使用的是sum>goal?不应该分类讨论n*(n-1)/2的奇偶然后对应是否加1,判断条件中位sum>=goal?
因为区间是前闭后开区间。在实现的过程中right=*max_element(x,x+n)-*min_element(x,x+n)+1。区间长度加大了1.原来偶数成为奇数,奇数成为偶数,所以若n*(n-1)/2为
偶数,n*(n-1)/2的中位数是不满足加1后的中位数。所以应该加1。若n*(n-1)/2为奇数,那么加1除以2后的值是满足的。而原式中n*(n-1)/2相对以前是少1的。所以应该加1.
综合,是sum>goal。。。
对于upper_bound。输出是rb,这是因为c的判断是可以统计小于或等于value的元素有多少个(所以要减1)。left是因为避免极端情况用上了-1.。。
但是为什么使用确定的中位数位置。这点我没理解。感觉有个数学推导。。。。所以我就掌握一种方法吧。哎╮(╯▽╰)╭。
另外一种方法不能理解。就背下来吧。。
完全没法做啊有木有。。。完全没思路。。。
然后看了题解。。。
主题思路。。
先对xi sort一下。然后进行第一次二分。
参考博客点击打开链接
c(x) 表示以x为相隔距离的个数能否大于等于c(n,2)/2个。能满足。不能就不满足。。。
好这里我有点卡了。大于c(n,2)/2怎么办?不是等于c(n,2)/2吗。。。好吧我蠢。
会不会一直大于c(n,2)/2个的距离。。。不会。。。。。
先写思路。。。
额,用low_bound和upper_bound两种方法写吧。。
使用low_bound的函数理解。。。
代码:
#include <iostream>#include <map>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <stack>#include <functional>#include <set>#include<sstream>#include <cmath>using namespace std;#define pb push_back#define PB pop_back#define bk back()#define fs first#define se second#define INF 1e18+10#define sq(x) (x)*(x)#define eps (1e-10)#define clr(x) memset((x),0,sizeof (x))#define cp(a,b) memcpy((a),(b),sizeof (b))typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> P;const int maxn=100100;int x[maxn];int n;ll goal;bool c(int mid){ ll sum=0; for(int i=0;i<n;i++) sum+=(n-1)-(lower_bound(x+i+1,x+n,x[i]+mid)-x)+1; //* return sum>goal;//*}int main(){ while(~scanf("%d",&n)) { for(int i=0;i<n;i++) scanf("%d",&x[i]); sort(x,x+n); goal=(n-1)*n>>2;//* int left=0;//* int right=*max_element(x,x+n)-*min_element(x,x+n)+1;//* int mid=0; while(right-left>1) { mid=(right+left)>>1; if(c(mid)) left=mid; else right=mid; } printf("%d\n",left); } return 0;}
细节理解。。。。
1.使用low_bound是为什么从a+i+1开始?
low_bound返回的是大于等于a[i]+val的第一个元素的地址。当val等于0时。返回的自身值的地址。这是不可取的。因为间隔的距离是不能与自身比较的。
2.(n-1)-(lower_bound(a+i+1,a+n,a[i]+val)-a)+1中为什么是n-1并且要+1?
(lower_bound(a+i+1,a+n,a[i]+val)-a)返回的是a数组的下标。下标的顶值是n-1,
加1,举个例子
0 1 2 3 4 5
2 3 5 8 9 10
假如a[i]+val=a[0]+val=2+1=3,那么返回的是1.n-5为5.5-1=4.而实际是4个元素,所以要加1.
3.right=*max_element(x,x+n)-*min_element(x,x+n)+1为什么要加1?
在c的判断函数中,if(sum > goal)是满足的,此时真值为left,这是为了避免极端情况当答案是一直向右二分,最后答案是right但是只能输出right-1,所以应该加1.
4.对中位数的表达中,为什么直接使用goal = n*(n-1)/4,然后在c的判断中使用的是sum>goal?不应该分类讨论n*(n-1)/2的奇偶然后对应是否加1,判断条件中位sum>=goal?
因为区间是前闭后开区间。在实现的过程中right=*max_element(x,x+n)-*min_element(x,x+n)+1。区间长度加大了1.原来偶数成为奇数,奇数成为偶数,所以若n*(n-1)/2为
偶数,n*(n-1)/2的中位数是不满足加1后的中位数。所以应该加1。若n*(n-1)/2为奇数,那么加1除以2后的值是满足的。而原式中n*(n-1)/2相对以前是少1的。所以应该加1.
综合,是sum>goal。。。
对于upper_bound。输出是rb,这是因为c的判断是可以统计小于或等于value的元素有多少个(所以要减1)。left是因为避免极端情况用上了-1.。。
但是为什么使用确定的中位数位置。这点我没理解。感觉有个数学推导。。。。所以我就掌握一种方法吧。哎╮(╯▽╰)╭。
另外一种方法不能理解。就背下来吧。。
还有5个题二分搜索这章就完了。。。。明天做完加上总结吧
codeforces的总结和区间dp的放在星期三。。。。。。 不慌不忙,不骄不躁。
0 0
- POJ-3579-Median
- Median - POJ 3579 二分
- POJ 3579 Median
- POJ 3579- Median
- POJ 3579 Median
- POJ - 3579 Median 二分
- poj-3579 Median
- POJ 3579 Median
- 【poj 3579】 Median
- POJ 3579 Median(二分)
- POJ 3579 median
- POJ 3579 Median
- POJ 3579 - Median(二分搜索)
- POJ 3579 Median 已翻译
- Median POJ
- POJ 3579 Median 查找中间值 二分
- poj 3579 Median 二分查找与lower_bound
- POJ 3579 Median (二分搜索)
- php生成网页桌面快捷方式
- Git下使用版本回退粗暴解决冲突问题
- 线性表链式存储结构实现 --单链表
- JSP实现HTML网页对Mysql数据库的数据修改
- 线性表链式存储结构实现--静态链表
- poj-3579 Median
- STL vector用法介绍
- 线性表链式存储结构实现 --单向循环链表
- 线性表链式存储结构实现 --双向循环链表
- linux下监测命令执行结果的工具watch小结
- 栈的顺序存储实现
- 黑马程序员——常用集合特点及其方法
- 栈的链式存储实现
- 和风天气-城市ID-sqlite数据库构建