组委会已经选择好了两块岩石作为比赛起点 0 和终点 L 。
在起点和终点之间,有 NN 块岩石(不含起点和终点的岩石)。
在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。
由于预算限制,组委会至多从起点和终点之间移走 MM 块岩石(不能移走起点和终点的岩石)。
如果长度 Len 可以满足,那么当长度小于 Len 时也可以满足,所以我们可以二分出最大的 Len。
首先验证答案具有单调性:拿走的石头越多,最短跳跃距离越大,这就叫答案的单调性。
然后进行实现。我们假设最短跳跃距离为mid,接着我们写一个check函数,判断一下这个mid是否合法,如果合法,就尝试找一找有没有一个值比mid更大(l=mid),如果不合法,就把mid减小(r=mid-1)。
check函数:我们遍历一遍每一块石头,累计出有多少块石头之间的间隔<=mid,如果超过m个,就不合法,如果小于等于m,就合法。
- #include
- typedef long long ll;
- using namespace std;
- int n, m, L;
- vector<int> d;
- bool check(int mx)
- {
- int cnt = 0, last = 0;
- for (int i = 0; i <= n; i ++ ) {
- if(d[i] - last < mx) cnt ++;
- else last = d[i];
- }
- return cnt <= m;
- }
- int main(){
- //std::ios::sync_with_stdio(false);
- //std::cin.tie(nullptr);
- cin >> L >> n >> m;
- d.resize(n);
- for (int i = 0; i < n; i ++ ) {
- cin >> d[i];
- }
- d.push_back(L);
- int l = 0, r = 1e9;
- while(l < r) {
- int mid = l + r + 1 >> 1;
- if(check(mid)) l = mid;
- else r = mid - 1;
- }
- cout << l << '\n';
- return 0;
- }