POJ 3579 Median
Posted IKnowYou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3579 Median相关的知识,希望对你有一定的参考价值。
传送门:http://poj.org/problem?id=3579
题意
给你n个数,然后求它们两两相减的绝对值,然后找出这些绝对值的中中位数。 解题思路:
- 先对n个数排序,那么最后的结果ans一定满足0<=ans<an-a1
- 第二如何判断ans就是我们需要求的值能,我们用二分进行逼近。l=0,r=an-a1,mid=(l+r)/2;
- 二分如何逼近呢,如何判断我们要求的答案ans是在[l,mid]还是在[mid,r]部分呢?
- 很明显是原数组两个数相减的绝对值<mid个数,和>mid的个数进行比较。(绝对值的个数<mid,ans在[mid,r]区间,否则在[l,mid]区间内
- 如何判段两数绝对值<mid的个数呢?
- 如何求一个数减去a[0]的值小于mid的个数,我们找到一个a[i]>=a[0]+mid时最小的一个i,那么数组[0,i)值减去a[0],都小于mid,这样枚举i就可以求得两数相减差值小于mid的个数。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN=1000005; int val[MAXN]; int N,M; bool calc(int mid){ int sum=0; //这儿如何计算绝对值<mid的个数. for(int i=0;i<N;i++) sum+=((lower_bound(val+i,val+N,val[i]+mid+1)-(val+i))-1); return sum>=M; } int main(){ while(scanf("%d",&N)!=EOF){ for(int i=0;i<N;i++){ scanf("%d",&val[i]); } M=(N*(N-1)/2+1)/2; sort(val,val+N); int l=0,r=val[N-1]-val[0]; while(r-l>1){ int mid=(l+r)>>1; if(calc(mid)) r=mid; else l=mid; } cout<<r<<endl; } return 0; }
以上是关于POJ 3579 Median的主要内容,如果未能解决你的问题,请参考以下文章