二分 P1824 进击的奶牛

二分 P1824 进击的奶牛

题目描述

Farmer John 建造了一个有 \(N\)\(2 \leq N \leq 10 ^ 5\)) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 \(x _ 1, x _ 2, \cdots, x _ N\)\(0 \leq x _ i \leq 10 ^ 9\))。

他的 \(C\)\(2 \leq C \leq N\))头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

输入格式

\(1\) 行:两个用空格隔开的数字 \(N\)\(C\)

\(2 \sim N+1\) 行:每行一个整数,表示每个隔间的坐标。

输出格式

输出只有一行,即相邻两头牛最大的最近距离。

输入输出样例 #1

输入 #1

5 3
1
2
8
4
9

输出 #1

3

思路

这道题可以类比二分经典题 “跳石头”,具体博客 这里tp

牛棚个数为 \(N\) ,要放置的牛的头数为 \(C\) ,且 \(2\le C\le N\),题面保证最近距离一定存在。


同 ”跳石头“,都是求 “最小值的最大”,可以得到最近距离的范围为 \(\left [\ 0, \ a[n] - a[1]\ \right ]\)

其中 \(a[n] - a[1]\) 为第 \(n\) 个牛棚到第 \(1\) 个牛棚的距离,为最远距离。

然后二分答案。

这里用了一个贪心的思想,就是第 \(1\) 个牛棚一定要有一头牛,这样才能保证 “最大” 这一前提,要不然最远距离小于 \(a[n] - a[1]\)


对要检查合法的距离 \(x\) ,遍历所有牛棚。

如果距前一个有牛的牛棚(定位牛棚) \(\ge\) 测试距离 \(x\) ,则更新定位牛棚为 \(a[i]\) ,且 cnt ++ (可以在这放头牛)。

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, c;
int a[N];

bool check(int x)// 检查最小距离为x时牛棚够不够
{
	int cnt = 1;// 第1个牛放在第1个牛棚
	int last = a[1];
	for (int i = 2; i <= n; i++) {
		// 如果两牛棚之间距离大于预设最短距离,可以在第i个牛棚放牛
		// 这样可以保证预设距离仍为最近距离
		if (a[i] - last >= x) cnt ++, last = a[i];
	}
	if (cnt >= c) return 1;// 牛棚够
	else return 0;
}

int main()
{
	cin >> n >> c;
	for (int i = 1; i <= n; i++) cin >> a[i];
	sort(a + 1, a + n + 1);
	int l = 0, r = a[n] - a[1];
	while (l < r) {
		int mid = (l + r + 1) >> 1;
		if (check(mid)) l = mid;
		else r = mid - 1;
	}
	cout << l;
}
posted @ 2025-05-23 12:57  AKgrid  阅读(31)  评论(0)    收藏  举报