洛谷题解:P2678 [NOIP2015 提高组] 跳石头

洛谷题解:P2678 [NOIP2015 提高组] 跳石头

题目:

这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。

输入格式:

第一行包含三个整数 n,m,分别表示矿石的个数、区间的个数和标准值。

接下来的 n 行,每行两个整数,中间用空格隔开,第 i+1 行表示 i 号矿石的重量 wi 和价值 vi。

接下来的 m 行,表示区间,每行两个整数,中间用空格隔开,第 i+n+1行表示区间 [li,ri] 的两个端点 li 和 ri。注意:不同区间可能重合或相互重叠。

输出格式:

第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1 且 N≥M≥0。

接下来 N 行,每行一个整数,第 i 行的整数 Di(0<Di<L), 表示第 i 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

样例:

输入:

25 5 2
2
11
14
17
21

输出:

4

分析:

这道题一般思路就是对于每一个可能的最小距离进行判断,在允许的范围内找到最大的最小距离。

直接执行的化应该是会TLE,这时候可以考虑二分,因为存在一个单调的关系,最小距离越大,需要去掉的石头越多,所以我们以最小距离为区间,找到最合适的去掉石头的个数。

这里道理想明白了其实就清楚了。

代码:

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>

using namespace std;

long long L,N,M;
long long D[100005] = {0};

bool check(long x)
{
    long long sum = 0;
    long long s = 0;
    for(long long i = 1;i <= N + 1;i++)
    {
        if(D[i] - s < x)
        {
            sum++;
        }
        else
        {
            s = D[i];
        }
    }
    return sum <= M;
}

int main()
{
    cin>>L>>N>>M;
    for(int i = 1;i <= N;i++)
    {
        cin>>D[i];
    }
    long long left = 1;
    long long right = L;
    D[N + 1] = L;
    while(left + 1 < right)
    {
        long long mid = (left + 1 + right) >> 1;
        if (check(mid))
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
    }
    if(check(right))
    {
        left = right;
    }
    cout<<left<<endl;
    return 0;
}
上一篇:[Noip2015] 信息传递


下一篇:【题解】 NOIP2015 运输计划