[luogu-2678]noip2015day2-T1 跳石头 题解

来源:互联网 发布:linux vi 文件末尾 编辑:程序博客网 时间:2024/05/22 01:56

题目传送门
题意解析:题目就是给了你n个在数轴上的点,然后还有起点和终点,坐标分别为0和n,然后去掉最多m个点(除了起点和终点),使剩下的点两两距离的最小值最大。


My opinion:这题唯一的问题是去掉的点不一定要取满m,只需要最后的最小值最大就行了,这时候如果我们知道答案的话,我们就可以判断,这个答案是否可行,而且如果x答案可行,那么x-1一定可行,如果x不可行,x+1一定不可行。所以可以使用二分答案法来寻找答案。
总结:
1、输入。
2、把答案从0到L二分。
3、判断这个答案是否可行。


神奇的代码:

#include<iostream>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define rep(i,a,n) for (int i=a;i<=n;i++)#define per(i,a,n) for (int i=a;i>=n;i--)#define Clear(a,x) memset(a,x,sizeof(a))#define ll long long#define INF 2000000000#define eps 1e-8using namespace std;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}const int maxn=50005;int d[maxn],a[maxn];int L,n,m;bool ok(int k){    int last=0,num=0;    rep(i,1,n+1){        if (d[i]-last<k) num++;            else last=d[i];        if (num>m) return false;     }    return true;}int main(){    L=read(),n=read(),m=read();    rep(i,1,n) d[i]=read();    d[0]=0,d[n+1]=L;    int l=0,r=L;    while (l<r){        int mid=(l+r+1)>>1;        if (ok(mid)) l=mid;            else r=mid-1;    }    printf("%d\n",l);    return 0;}
原创粉丝点击