欢乐赛D

POJ2456
原题链接https://vjudge.net/contest/350953#problem/D
在这里插入图片描述
大概提题意为对于选取有n个点在不同的位置,选取在选取其中x个点的情况下找出每两个点之间的间距的最小的间距的最大值。
本题使用二分法来做,对于可以取的每个间距二分查找一下,找到题目要求的值即可。
我们需要找最大的最小区间,检验方法就是判断所有比当前值大的位置能不能把x个点装下即可。
二分法:
对于1 2 3 4 5 6 7 8 9 10;
二分法就是每次查找我们找到的区间的正中间的值,以此来将查找区间减半
首先查找5,如果5符合题意,就证明5以下的值都符合题意,但是要求最大值,显然5最大,那么1-4就不用再考虑,再次在5-10二分查找,验8;
假如5不符合题意,那么就说明大于5的点不够将所有的点装下,同理5既然不能使用5-10就都不能使用,接下来验证1-4,也就是验2;
二分就分为这两种情况,往下一直验证,将所有情况遍历一遍即可。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
long long a[100005];
int main()
{
	long long n, m;
	scanf("%lld %lld", &n, &m);
	long long i;
	for (i = 0; i < n; i++)
	{
		scanf("%lld", &a[i]);
	}
	sort(a, a + n);//从小到大排序
	long long s = a[0];//最小值
	long long e = a[n - 1];//最大值
	long long ans;
	while (s <= e)//结束条件 将所有情况遍历
	{
		long long mid = (e + s) / 2;//二分
		long long sum = 1;
		long long z = 0;
		for (i = 1; i < n; i++)
		{
			if (a[i] - a[z] >= mid)//判断区间大于Mid的点的数量
			{
				sum++;
				z = i;
			}
		}
		if (sum >= m)//判断数量是否足够装下所有的点,进行二分的两种情况
		{
			s = mid + 1;
			ans = mid;
		}
		else
		{
			e = mid - 1;
		}
	}
	printf("%lld", ans);
	return 0;
}
发布了130 篇原创文章 · 获赞 3 · 访问量 1602

猜你喜欢

转载自blog.csdn.net/yeyuluo/article/details/103957244
今日推荐