题意是一个数轴上有一些石头,有个青蛙要从左边跳到右边,他一次最多能跳L步,然后他会尽可能少跳,你是上帝可以通过加石头来使他多跳,问最多能让青蛙跳几步。
是一个贪心的方法,需要记录该步前面一步的位置和当前位置,然后如果当前位置到当前位置加上L范围内有石头,那么直接跳到能跳的最远处,反之,放一个石头在前面一步位置加上L+1,当然,可能下一个石头的位置非常远而L又比较小,所以需要优化,需要推出公式,我就这里被坑到了。。直到比赛后才找到错误。。还有看别人写的好简单。。我写的好复杂。。真是智商的差距么。。好伤心
AC代码:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<string.h>
#include<string>
using namespace std;
#define ll __int64
#define eps 1e-10
#define MOD 10000007
template<class T>
inline void scan_d(T &ret)
{
char c;
ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
ll a[200005];
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o4.txt","w",stdout);
#endif // GLQ
int t,i,n,cas=1;;
scanf("%d",&t);
while(t--)
{
ll m,l;
scanf("%d%I64d%I64d",&n,&m,&l);
for(i = 0; i < n; i++)
scan_d(a[i]);
sort(a,a+n);
ll pre,pos;
a[n] = m;
for(i = 0; i <= n && a[i] <= l; i++);
if(i == 0)
{
pre = 0;
pos = 1;
}
else
{
pre = 0;
pos = a[i-1];
}
ll ans = 1;
while(1)
{
if(pos+l >= m)
{
if(pos < m) ans++;
break;
}
int flag = 0;
while(pos+l >= a[i] && i < n)
{
flag = 1;
i++;
}
if(flag) i--;
if(pos+l < a[i] || i >= n)
{
ll temp = pre;
// cout<<"a:"<<a[i]<<" "<<pre<<" "<<pos<<" "<<ans<<endl;
ll t1 = (a[i]-pre)/(l+(ll)1);
pre = pos+(t1-(ll)1)*(l+(ll)1);
// cout<<pre<<endl;
pos = temp+t1*(l+(ll)1);
ans += 2*t1-(ll)1;
while(pre+l>=a[i])//已经可以到达a[i]了
{
pos = a[i];
i++;
}
// cout<<a[i]<<" "<<pre<<" "<<pos<<" "<<ans<<endl;
if(pre+l>=m)
{
break;
}
}
else
{
// cout<<pre<<" "<<pos<<" "<<pos-pre<<" "<<a[i]<<" "<<a[i-1]<<" "<<ans<<endl;
pre = pos;
pos = a[i];
ans++;
i++;
}
// cout<<ans<<" "<<pre<<" "<<pos<<endl;
}
printf("Case #%d: %I64d\n",cas++,ans);
}
return 0;
}