P2678 跳石头

传送门

思路:

  二分跳跃的最短距离 mid 。暴力判断如果有两个石头直接的距离小于 mid ,就把这个石头拿走。如果拿走的石头数目 cnt ≤ m,说明二分的答案可行,ans = mid,接着二分更短的跳跃距离。 

Code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<set>
using namespace std;
#define lck_max(a,b) ((a)>(b)?(a):(b))
#define lck_min(a,b) ((a)<(b)?(a):(b))
typedef long long LL;
const int maxn=5e5+7;
LL d,n,m;
LL t[maxn];
inline LL read()
{
    LL kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(ls^45))
            kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return xs*kr;
}
inline void out(LL xs)
{
    if(!xs) {putchar(48); return;}
    if(xs<0) putchar('-'),xs=-xs;
    int kr[57],ls=0;
    while(xs) kr[++ls]=xs%10,xs/=10;
    while(ls) putchar(kr[ls]+48),ls--;
}
LL cnt,i,now;
inline bool check(LL u)
{
    cnt=0,i=0,now=0;
    while(i<=n)
    {
        i++;
        if(t[i]-t[now]<u) 
            cnt++;
        else
            now=i; 
    }
    if(cnt>m)
        return false;
    else
        return true;
}
LL ans;
inline void query(LL l,LL r)
{
    while(l<=r)
    {
        LL mid=l+r>>1;
        if(check(mid))
            ans=mid,l=mid+1;
        else
            r=mid-1;
    }
}
int main()
{
    d=read();n=read();m=read();
    for(LL i=1;i<=n;i++)
        t[i]=read();
    t[n+1]=d;//终点到起点的距离。 
    query(1,d);
    out(ans),putchar('\n');
return 0;
}

 

posted @ 2018-10-26 15:21  落笔映惆怅丶  阅读(234)  评论(0编辑  收藏  举报