BZOJ 4385 Wilcze doły
2018.05.15
2018.05.15
给定一个长度为$n$的序列,你有一次机会选中一段连续的长度不超过$d$的区间,将里面所有数字全部修改为$0$。 请找到最长的一段连续区间,使得该区间内所有数字之和不超过$p$。
首先预处理出所有长度为$d$的区间的权值和。把他们放到一个单调栈中。之后双指针扫一下,对于每一个右端点求出最靠左的左端点。
傻题,没啥特殊需要处理的。
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
typedef long long ll;
inline char nc()
{
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline ll ri()
{
ll ret=0;char tmp=nc();
while(!isdigit(tmp)) tmp=nc();
while(isdigit(tmp)) ret=ret*10+(tmp-'0'),tmp=nc();
return ret;
}
int n,d,q[2000010],l=1,r=0,ans;
ll p,sum[2000010],f[2000010];
int main()
{
int i,j;
n=ri(),p=ri(),d=ri();
for(i=1;i<=n;++i) sum[i]=sum[i-1]+ri();
for(i=1;i+d-1<=n;++i) f[i]=sum[i+d-1]-sum[i-1];
for(i=d,j=0;i<=n;++i)
{
while(l<=r&&f[q[r]]<=f[i-d+1]) --r;
q[++r]=i-d+1;
while(sum[i]-sum[j]-f[q[l]]>p)
{
++j;
while(q[l]<=j) ++l;
}
ans=max(ans,i-j);
}
printf("%d\n",ans);
return 0;
}