一道典型的单调队列优化dp,想了好久才搞清楚。
是典型的限制长度的最大子段和,基本的dp方程应该是dp[i]=sum[i]-min{sum[j]}
其中sum是原数组的前缀和,j的下标应当满足(i-j)<t,t是限制的长度。
单调队列里塞进下标,维护这些下标处的前缀和单调不减,每次更新答案为sum[i]-sum[j]即可。
坑点究极多,每次更新ans=max(ans,sum[i])还不行,一定得在一开始往队列里塞个下标0进去才能维护得住单调性。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll inf=1e18; const int maxn=300005; int s,t; ll a,sum[maxn],ans=-inf,mx=-inf; deque<ll> q; int main(){ scanf("%d%d",&s,&t); for(int i=1;i<=s;++i){ scanf("%lld",&a); mx=max(mx,a); sum[i]=sum[i-1]+a; } q.push_back(0); for(int i=1;i<=s;++i){ // ans=max(ans,sum[i]); while(!q.empty()&&sum[i]<sum[q.back()]) q.pop_back(); while(!q.empty()&&i-q.front()>t) q.pop_front(); q.push_back(i); ans=max(ans,sum[i]-sum[q.front()]); // for(int j=0;j<q.size();++j) // cout<<q[j]<<' ';cout<<endl; } if(mx<=0) printf("%lld",mx); else printf("%lld",ans); return 0; } /* 3 3 2 -1 3 */