最大子序和
题目链接:https://www.acwing.com/problem/content/137/
首先我们可以枚举右端点i,当i固定时,问题就变为:找到一个左端点j,其中j在[i-m,i-1],并且s[j]最小。
我们可以假设任意两个位置j和k,如果k<j<i并且s[k]>=s[j],那么对于所有>=i的右端点,k永远不会成
为最好的选择。所有可能成为最好选择的策略是:下标位置递增,对应的前缀和S的值也递增
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<map> using namespace std; int a[300005],q[300005],sum[300005]; int main() { int i,j,m,n,ans,w,k,l,r; while(~scanf("%d %d",&n,&m)) { for(i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } l=r=1; q[1]=0; ans=-9999999; for(i=1;i<=n;i++) { while(l<=r&&q[l]<i-m) l++; ans=max(ans,sum[i]-sum[q[l]]); while(l<=r&&sum[q[r]]>sum[i]) r--; q[++r]=i; } printf("%d\n",ans); } return 0; }