这个题呢是要求最大不定长子序列
kkk的题解启发了我
d
p
[
i
]
=
m
a
x
{
s
u
m
[
i
]
−
s
u
m
[
j
]
}
(
j
∈
[
i
−
m
,
i
−
1
]
)
dp[i]=max \lbrace sum[i]-sum[j] \rbrace (j\in[i-m,i-1])
dp[i]=max{sum[i]−sum[j]}(j∈[i−m,i−1]) 这个范围也很有意思,因为是前缀和
然后转化最骚气: d p [ i ] = s u m [ i ] − m i n { s u m [ j ] } dp[i]=sum[i]-min\lbrace sum[j] \rbrace dp[i]=sum[i]−min{sum[j]} 这不就是让我们维护m为区间长度上限的最小值吗?!
这个题现在是个对我来说是个橙题了 但是我自己写卡住的原因是维护最大值有点懵 这也体现出了我对单调队列理解的匮乏
既然单调队列维护的是你当前区间的最小值,那直接用区间的右端点减去最小值维护最大值就行了
感觉对单调队列的理解已经是小学生水准了%%%
最后还有一个坑点!!!最初的时候别忘了把0压进队列,因为有这样的hack数据5 2 1 -10 -10 -10 -10 -10。。。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=5e5+10;
int n,m,a[N];ll sum[N],ans;
deque<int>q;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
q.push_back(0);
for(int i=1;i<=n;++i){
while(!q.empty()&&sum[q.back()]>=sum[i]) q.pop_back();
q.push_back(i);
ans=max(ans,sum[i]-sum[q.front()]);
if(i-q.front()>=m) q.pop_front();
}
printf("%lld\n",ans);
return 0;
}