题目大意:给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0
请找到最长的一段连续区间,使得该区间内所有数字之和不超过p
题解:权值非负,显然取长度为d的区间
由于区间长度固定,预处理g[i]=sum(a[i]–a[i-d+1]),这样就把区间转成了易于维护的点
枚举右端点R,随着R的增大,最优的L单调不减,可以使用尺取法
现在需要维护g[]的最值,这个就是滑动窗口
我的收获:……
#include <iostream>
#include <cstdio>
using namespace std;
const int M=2000005;
int n,d,ans,q[M];
long long p,f[M],g[M],s[M];
void work()
{
int l=1,r=0;
for(int L=1,R=d;R<=n;R++){
int now=R-d+1;
while(l<=r&&g[now]>g[q[r]]) r--;
q[++r]=now;
while(s[R]-s[L-1]-g[q[l]]>p){
L++;if(l<=r&&q[l]<L) l++;
}
ans=max(ans,R-L+1);
}
cout<<ans<<endl;
}
void init()
{
cin>>n>>p>>d;
for(int i=1;i<=n;i++) scanf("%lld",&s[i]),s[i]+=s[i-1];
for(int i=1;i<=n;i++) g[i]=s[min(i+d-1,n)]-s[i-1];//g[i]=sum(a[i]--a[i+d-1])
}
int main()
{
init();
work();
return 0;
}