思路
二分空题段长度,然后dp,用线段树维护
code
#include<bits/stdc++.h>
#define inf 1000000007
using namespace std;
int n,m,ans,a[50005],f[50005],tr[3000005];
long long find(int l,int r,int k,int x,int y)
{
if(x>y)return 0;
if(l==x&&r==y)
{
return tr[k];
}
int mid=(l+r)/2;
if(y<=mid)return find(l,mid,k*2,x,y);
if(x>mid)return find(mid+1,r,k*2+1,x,y);
return min(find(l,mid,k*2,x,mid),find(mid+1,r,k*2+1,mid+1,y));
}
void build(int l,int r,int k)
{
tr[k]=10000000000000000;
if(l==r)return;
int mid=(l+r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
}
void fix(int l,int r,int k,int x)
{
if(l==r)
{
tr[k]=f[x];
}
else
{
int mid=(l+r)/2;
if(x<=mid)fix(l,mid,k*2,x);
else fix(mid+1,r,k*2+1,x);
tr[k]=min(tr[k*2],tr[k*2+1]);
}
}
bool dp(int s)
{
build(1,n,1);
for(int i=1;i<=n;i++)
{
int sum;
if(i-s-1<=0||i==1)sum=0;
else sum=find(1,n,1,i-s-1,i-1);
f[i]=sum+a[i];
fix(1,n,1,i);
}
for(int j=n;j>=n-s;j--)
{
if(f[j]<=m)return 1;
}return 0;
}
int main ()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)/2;
if(dp(mid))
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
printf("%d\n",ans);
return 0;
}