先想一下思路,由于是区间跳跃,不能用贪心,那么f[i]表示跳到i时最少踩到的石子数,i只能由i-t~i-s转移过来,所以选择其中的最小值跳,保证f[i]最小。
但是l太大了,1e9,但是m和t很小,就是1e9中有很多没有用的空间,我们求终点的值,所以中间废掉的空间可以省略,缩点之后用还能用单调队列优化一下。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<algorithm>
using namespace std;
int r,s,t,m,a[10001],b[101],maxx,f[10001],cha[102],q[100001],head=1,tail=0;
int cmp(int x,int y)
{
return x<y;
}
int main()
{
cin>>r>>s>>t>>m;
for(int i=1;i<=m;++i)
cin>>a[i];
if(s==t)
{
int ans=0;
for(int i=1;i<=m;++i)
if(a[i]%s==0) ans++;
cout<<ans;
return 0;
}
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;++i)
{
cha[i]=a[i]-a[i-1];
if(cha[i]>90) cha[i]=90;
}cha[m+1]=min(r-a[m],100);
memset(a,0,sizeof(a));int l=0;
for(int i=1;i<=m;++i)
{
l+=cha[i];
a[l]=1;
}
l+=cha[m+1];
for(int i=0;i<=l+10;++i)
f[i]=99999;
f[0]=0;int cnt=1;
for(int i=1;i<l+10;++i)
{
if(q[head]<i-t&&head<=tail) head++;
while(f[i-s]<=f[q[tail]]&&head<=tail) tail--;
if(i-s>=0)q[++tail]=i-s;
f[i]=f[q[head]]+a[i];
if(i-s<0) f[i]=999999;
}int ans=999999;
for(int i=l;i<l+10;++i)
if(f[i]<ans) ans=f[i];
cout<<ans;
return 0;
}