题目链接:https://ac.nowcoder.com/acm/problem/16462
题意:给三个整数L,N,K,分别表示终点坐标(起点为0),石子个数,最多去掉石子的个数。(0<=M<=N<=5e4,1<=L<=1e9)。
要求去掉k个石子后两个石子的最小距离的最大值。
题解:求最小值的最大值,二分。
贪心策略:假设答案为ans,从头开始,如果a[i]-a[i-1]>=ans,那么肯定最好不取a[i],否则就取a[i]。边界讨论--最后一步如果L-a[n]<ans,不去L去a[n]。
一个很重要的总结:题的广度,也还是需要上去的,现在这考前,也不是多有一整块的时间,但是每次cf还是坚持去打的,准备打cf的那一天晚上必然还是要准备一下编程,那么刷题不刷字符串的基础只是题,拓展一下广度,在洛谷随便挑题做,10分钟没头绪立马看解答,尽量看懂,看不懂的就放在那里。(也许希哥就是这样淦的,可我到现在才理解,倒也不玩晚,准备明年蓝桥杯嘛,争取拿个B组国一(其实国二就很满足了),另外还是刷一下六级,也当是准备考研了(就算最后不保,至少可以写在简历上,如果能刷到550,应该是个很不错的结果了(有点异想天开,其实425就很强了),到时候,坚持每周都刷一刷就好了,我应该还是知道自己应该做什么吧!!))
代码:
#include <bits/stdc++.h>
#define ll long long
#define ld double
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x,y) make_pair(x,y)
#define rep(i,a,n) for(ll i=a;i<=n;i++)
#define per(i,n,a) for(ll i=n;i>=a;i--)
#define dbg(x) cout << #x << "===" << x << endl
#define dbgg(l,r,x) for(ll i=l;i<=r;i++) cout<<x[i]<<" ";cout<<"<<<"<<#x;cout<<endl
using namespace std;
template<class T>void read(T &x){T res=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){res=(res<<3)+(res<<1)+c-'0';c=getchar();}x=res*f;}
inline void print(ll x){if(x<0){putchar('-');x=-x;}if(x>9)print(x/10);putchar(x%10+'0');}
const ll maxn = 1e5 + 10;
const ll mod = 1e9+7;
ll n,a[maxn],k,len;
bool ok(ll x){
ll res=0,p=a[0];
rep(i,1,n+1){
if(a[i]-p<x) res++;
else p=a[i];
}
// cout<<x<<" "<<res<<endl;
if(res<=k) return true;
else return false;
}
int main() {
ll _s = 1;
// read(_s);
//freopen("testdata.in","r",stdin);
//freopen("testout.out","w",stdout);
for (ll _=1;_<=_s;_++) {
read(len),read(n),read(k);
rep(i,1,n) read(a[i]);a[n+1]=len;
ll l=0,r=1e18;
while(l<r){
ll mid=(l+r+1)/2;//?加不加1看ok是是否为r=mid+1或l=mid
if(ok(mid)) l=mid;
else r=mid-1;
}
cout<<r<<endl;
}
return 0;
}