您的位置:首页 > 其它

poj-3579 Median

2015-12-29 01:48 323 查看
题意给你n个数。两两相差的绝对值有c(n,2)个,有这c(n,2)个数的中位数

完全没法做啊有木有。。。完全没思路。。。

然后看了题解。。。

主题思路。。

先对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的放在星期三。。。。。。 不慌不忙,不骄不躁。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: