StkOvflow

STACK OVERFLOW!

一言(ヒトコト)

跳石头(NOIP2015)

AcWing
洛谷

解题思路

这题看到最短跳跃距离尽可能长就会想到二分
但是我们二分的\(check\)函数怎么写呢
可以看到限制条件移走的石头最多只能是\(m\)
我们二分这个最短距离
容易想到一个贪心策略:扫描一遍\(a\)数组,如果\(a_{i} - a_{now} < mid\),(\(now\)是当前站的石头,一开始在岸上,所以是\(now = 0\)),那因为此时\(mid\)是移走后的两块石头间的最短距离,不存在有两块石头的距离\(D < mid\) ,所以第\(i\)块必须移走, \(cnt ++\)(\(cnt\)是移走的总数),最后判断一下是否(\(cnt <= m\))即可

模板选用

\(我们是为了二分出满足check函数的最大值,所以是这个样子(o表示满足check,\)
\(.是不满足,v是分界也满足)\)

oooooooooooooov..............

选用二分模板如下

int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return r;
}

代码

#include <iostream>

using namespace std;

const int N = 5e5 + 10;
int a[N], n, m, L;

bool check(int x) 
{
    int cnt = 0, now = 0;
    for (int i = 1; i <= n; i ++ ) 
        if (a[i] - a[now] < x) cnt ++ ;
        else now = i;
    return cnt <= m;
}

int main()
{
    scanf("%d%d%d", &L, &n, &m);
    
    for (int i = 1; i <= n; i ++ ) 
        scanf("%d", &a[i]);
    a[ ++ n] = L;
    
    int l = 0, r = L;
    while (l < r) 
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    printf("%d\n", r);
    
    return 0;
}
posted @ 2022-12-20 22:43  StkOvflow  阅读(52)  评论(0)    收藏  举报