【POJ 3258】 River Hopscotch 二分答案

Description

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 ≤ M ≤ N).

FJ wants to know exactly how much he can increase the shortest distance before he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input

Line 1: Three space-separated integers: L, N, and M
Lines 2…N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.
Output

Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks
Sample Input

25 5 2
2
14
11
21
17
Sample Output

4
Hint

Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).

題意:給定起點和終點,以及中間的n個座標,要去掉m個座標,使得兩點間的最小值最大

思路(二分答案):

經典的二分答案例題,要求最小值最大化。我們可以二分最小值,如果這個最小值能限制在去掉m個座標仍滿足的條件下,就嘗試讓這個最小值變大一點(L = mid + 1),否則說明這個最小值太大了,條件過於嚴格,因爲這樣會產生只去掉m個座標還有更小的距離產生,所以就要下調最小值(R = mid-1)。
至於怎麼check每個mid,就先將座標排序,然後從頭到尾看相鄰兩點距離,如果產生了比當前mid要小的,就用掉m中的一個,把當前點刪除,繼續往後看,最後再判斷最後一個點到終點是否滿足題意即可。

AC代碼:

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int maxn = 1e5+5;
const int maxm = 100000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
//const double pi=acos(-1);
const int mod = 1e9+7;
inline int lowbit(int x)
{
    return x&(-x);
}
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(!b)
    {
        d=a,x=1,y=0;    //x=(x%(b/d)+(b/d))%(b/d);
    }
    else
    {
        ex_gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
inline ll qpow(ll a,ll b,ll MOD=mod)
{
    ll res=1;
    a%=MOD;
    while(b>0)
    {
        if(b&1)res=res*a%MOD;
        a=a*a%MOD;
        b>>=1;
    }
    return res;
}
inline ll inv(ll x,ll p)
{
    return qpow(x,p-2,p);
}
inline ll Jos(ll n,ll k,ll s=1)
{
    ll res=0;
    rep(i,1,n+1) res=(res+k)%i;
    return (res+s)%n;
}
inline ll read()
{
    ll x=0;
    char ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0', ch=getchar();
    return x;
}
//
ll n,dis, m;
ll a[maxn];

ll cal(ll x)
{
    ll t = 0;
    ll cnt = 0;
    bool flag = 1;
    rep(i,1,n)
    {
        if(a[i]-t<x)
            cnt++;
        else t = a[i];
    }
    if(cnt<=m&&dis-t>=x) flag = 1;
    else flag = 0;
    return flag;
}

int main()
{
    dis = read();
    n = read();
    m = read();
    for(ll i=1; i<=n; i++)
        a[i] = read();
    sort(a+1,a+1+n);
    ll L = 0, R = dis;
    ll ans = R;
    while(L<=R)
    {
        ll mid = (L+R)>>1;
        if(cal(mid))
            L = mid + 1, ans = mid;
        else
            R = mid-1;
    }
    cout<<ans<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章