您的位置:首页 > 其它

poj3579,二分找答案,再二分查找

2015-10-31 18:52 260 查看
题意:

给一堆数,先求出所有两个数的差值;

输出这些数的中位数;

理解:

直接枚举这些数肯定会超时,因为有C(n, 2)个,这是非常大的;

我开始是直接枚举我们要求的第中位数个的值,但这个数也是非常大的;

然后看了下别人的思路,发现我依然天真。。。

是这样的,先二分找答案,就是在一个范围内二分枚举答案;

判断这个答案是否行得通;

怎么判断呢?

二分查找在这个值的基础上有几个大于它的,即为不在该范围内的数;

我也不懂怎么要这样去找,但它就是对的。。。。

可能是因为这个值恰好比前面的那些差值大于等于,而这个数就是答案。

代码如下:

代码最能说明为什么,当然也需要模拟。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string>
#include <set>
#include <cmath>

using namespace std;

#define maxn 100100
#define x first
#define y second
#define ll long long
#define P pair<ll, ll>
#define INF 1e9

int a[maxn];

bool solve(int t, int m, int n)
{
int count = 0;
for (int i = 0; i < n; ++i)
{
count += n - (lower_bound(a, a + n, a[i] + t) - a);  //二分找位置,以确定答案是否可行
}
if (count <= m)
{
return false;
}
else return true;
}

int main()
{
int n;
while(~scanf("%d", &n))
{
for (int i = 0; i < n; ++i)
{
scanf("%d", &a[i]);
}
sort(a, a + n);

ll m = n * (n - 1) / 4;
int lb = 0, rb = a[n - 1]; //答案一定存在这两个之间
while(rb - lb > 1)  //二分答案
{
int mid = (lb + rb) / 2;
if (solve(mid, m, n))
{
lb = mid;
}
else
{
rb = mid;
}
}
printf("%d\n", lb);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息