前言
本题链接 :
滑动窗口 : 维护一个大小为
k
k
k 的 区间的 最大值和 最小值
思路
取 f [ i ] f[i] f[i]表示 以 a [ i ] a[i] a[i]结尾,长度不超过 m m m最大值
对于区间和 : 我们可以用前缀和维护 s u m [ r ] − s u m [ l ] sum[r] - sum[l] sum[r]−sum[l]
因此暴力做法 可以对于每一个 i i i我们都枚举左端点 :
f
[
i
]
=
m
a
x
(
S
[
i
]
−
S
[
j
]
)
(
1
<
=
i
−
j
<
=
m
)
f[i] = max(S[i] - S[j]) (1<=i-j<=m)
f[i]=max(S[i]−S[j])(1<=i−j<=m)
即 :
f
[
i
]
=
S
[
i
]
−
m
i
n
S
[
j
]
(
1
<
=
i
−
j
<
=
m
)
f[i] =S[i] - min S[j] (1<=i-j<=m)
f[i]=S[i]−minS[j](1<=i−j<=m)
因此我们可以通过单调队列优化
即 :
从前往后,记录一个长度不超过
m
m
m的区间最小值
CODE
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10,INF =1e9;
int n,m;
int s[N],q[N];
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>s[i],s[i]+=s[i-1];
int res = -INF;
int hh = 0 ,tt = 0 ;
for(int i=1;i<=n;i++)
{
if(q[hh]<i-m) hh++;
res = max(res,s[i]-s[q[hh]]);
while(hh<=tt && s[q[tt]] >= s[i])
tt--;
q[++tt] = i;
}
cout<<res<<endl;
}
int main()
{
ios::sync_with_stdio(false);
solve();
return 0;
}