BZOJ4385 [POI2015]Wilcze doły

题面在这里

首先很明显选择删除的区间长度为d

那么定义\(g_i=s_i-s_{i-d+1}\)表示以i为结尾的区间和

然后two pointers枚举区间,满足\(s_{(i,j)}-g_{max}\le p\)

\(g_{max}\)就是区间内g的最大值,用单调队列维护就好了

示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*l=buf,*r=buf;
return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
inline int red(){
int res=0,f=1;char ch=nc();
while (ch<'0'||'9'<ch) {if (ch=='-') f=-f;ch=nc();}
while ('0'<=ch&&ch<='9') res=res*10+ch-48,ch=nc();
return res*f;
}

const int maxn=2000005;
int n,l,a[maxn],que[maxn];
ll s[maxn],g[maxn],S;
int main(){
scanf("%d%lld%d",&n,&S,&l);
for (int i=1;i<=n;i++) a[i]=red(),s[i]=s[i-1]+a[i],g[i]=s[i]-s[max(i-l,0)];
int ans=l,hed=1,til=0;
for (int i=1,j=1;i<=n;i++){
while (hed<=til&&g[que[til]]<=g[i]) til--;
que[++til]=i;
while (s[i]-s[j-1]-g[que[hed]]>S){
j++;if (hed<=til&&que[hed]-l<j-1) hed++;
}
ans=max(ans,i-j+1);
}
printf("%d",ans);
return 0;
}