poj-3579 Median

来源:互联网 发布:黑帮之地mac 编辑:程序博客网 时间:2024/04/28 11:05
题意给你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的放在星期三。。。。。。 不慌不忙,不骄不躁。

0 0