进击的奶牛
题目描述
Farmer John 建造了一个有
n
n
n(
2
2
2
≤
\le
≤
n
n
n
≤
\le
≤
100000
100000
100000) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是
x
1
x_1
x1 ,…,
x
n
x_n
xn
(0
≤
\le
≤
x
i
x_i
xi
≤
\le
≤
1000000000
1000000000
1000000000)。
他的 C C C( 2 2 2 ≤ \le ≤ C C C ≤ \le ≤ n n n) 头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?
输入格式
第 1 1 1 行:两个用空格隔开的数字 n n n 和 C C C。
第 2 2 2 ~ n + 1 n+1 n+1 行:每行一个整数,表示每个隔间的坐标。
输出格式
输出只有一行,即相邻两头牛最大的最近距离。
样例 #1
样例输入 #1
5 3
1
2
8
4
9
样例输出 #1
3
Code
讲解都在注释里:
// Problem: P1824 进击的奶牛
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1824
// Memory Limit: 125 MB
// Time Limit: 1000 ms
#include <bits/stdc++.h>
using namespace std;
int n, c, x, a[100005];
bool check(int mid) // 判断是否为可行解
{
int num = 0; // 记录 mid 使用的牛栏数量
int l = a[1]; // 记录上一只牛的位置(初始化时牛在第一个牛栏)
for (int i(2); i <= n; ++i) // 依次枚举每头牛
{
if (a[i] - l < mid)
++num; // 距离不够,把当前牛放在下一个牛栏
else
l = a[i]; // 否则更新上一头牛的位置
if (num > x)
return false; // 需要牛栏比总牛栏数大
}
return true;
}
int main()
{
cin >> n >> c;
for (int i(1); i <= n; ++i)
cin >> a[i];
sort(a + 1, a + n + 1); // 对 a 数组进行排序
x = n - c; // 剩余的牛栏数目
int l, r, mid;
l = 1, r = a[n] - a[1]; // 可能答案的左边界(1)与右边界(a[n]-a[1])
while (l + 1 < r)
{
mid = (l + r) / 2; //[l, mid], [mid, r]
if (check(mid))
l = mid; //[mid, r]
else
r = mid; //[l, mid]
}
if (check(r))
cout << r;
else
cout << l;
}
再来一个没有注释的版本: