一年一度的「跳石頭」比賽又要開始了!ios
這項比賽將在一條筆直的河道中進行,河道中分佈着一些巨大岩石。組委會已經選擇好了兩塊岩石做爲比賽起點和終點。在起點和終點之間,有 \(N\) 塊岩石(不含起點和終點的岩石)。在比勝過程中,選手們將從起點出發,每一步跳向相鄰的岩石,直至到達終點。git
爲了提升比賽難度,組委會計劃移走一些岩石,使得選手們在比勝過程中的最短跳躍距離儘量長。因爲預算限制,組委會至多從起點和終點之間移走 \(M\) 塊岩石(不能移走起點和終點的岩石)。spa
第一行包含三個整數 \(L,N,M\),分別表示起點到終點的距離,起點和終點之間的岩石數,以及組委會至多移走的岩石數。保證 \(L \geq 1\) 且 \(N \geq M \geq 0\)。code
接下來 \(N\) 行,每行一個整數,第 \(i\) 行的整數 \(D_i( 0 < D_i < L)\), 表示第 \(i\) 塊岩石與起點的距離。這些岩石按與起點距離從小到大的順序給出,且不會有兩個岩石出如今同一個位置。get
一個整數,即最短跳躍距離的最大值。string
輸入 #1it
25 5 2 2 11 14 17 21
輸出 #1io
4
輸入輸出樣例 \(1\) 說明:將與起點距離爲 \(2\) 和 \(14\) 的兩個岩石移走後,最短的跳躍距離爲 \(4\) (從與起點距離 \(17\) 的岩石跳到距離 \(21\) 的岩石,或者從距離 \(21\) 的岩石跳到終點)。class
另:對於 \(20\%\)的數據,\(0 \leq M \leq N \leq 10\)。stream
對於\(50\%\)的數據,\(0 ≤ M ≤ N ≤ 100\)。
對於 \(100\%\)的數據,\(0 \leq M \leq N \leq 50,000,1 \leq L \leq 1,000,000,000\)。
容易想到二分答案。考慮如何\(check\)。貪心地找第一個比須要\(check\)的長度距目前位置距離大的石頭並跳到該處,加上中間跳過的全部石頭做爲答案。
注意在處理終點時,若是終點距離目前點的位置比須要\(check\)的長度小,則上次跳到這裏的行爲時不合法的,應當直接跳過該石頭跳到終點,即答案\(+1\)。
上代碼。注意上面那個地方有\(10pts\)分值。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<cctype> #define int long long #define rep(i,a,n) for(register int i=a;i<=n;i++) #define dep(i,n,a) for(register int i=n;i>=a;i--) using namespace std; int l,n,m,d[100050]; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } void write(int x) { if(x<0)putchar('-'),x=-x; if(x==0)return; write(x/10); putchar('0'+x%10); } bool check(int len) { int now=0; int cnt=0; rep(i,1,n-1) { if(d[i]-now>=len)now=d[i]; else ++cnt; if(cnt>m)return false; } if(d[n]-now<len)++cnt; if(cnt>m)return false; return true; } signed main() { l=read(),n=read(),m=read(); rep(i,1,n)d[i]=read(); d[n+1]=l; ++n; int ll=1,rr=l; while(ll<rr-1) { int mid=(ll+rr)>>1; if(check(mid))ll=mid; else rr=mid; } int ans; if(check(rr))ans=rr; else if(check(ll))ans=ll; write(ans); return 0; }