最大子序和
题目 最大子序和
思路分析
首先很容易想到前缀和
问题转变成对于每个r找一个窗口中的最小的l-1
可以挖掘出一些性质
如果-2加入 那它左边的1就绝对不会是答案 因为1本身就在左边 会先出队 所以1可以删除
而-2右边的3有可能作为答案 因为-2在左边 它会先从窗口划出去
所以这个队列里的数应该是单调递增的
我们要的答案就是队头的那个最小的数
单调队列 模版中的找最小值
注意一个问题 5的要找的答案应该是那个-2 (s[r]-s[l-1])
窗口在5加入之前得出答案 而不是5加入后得到答案
所以先求res再插入5 对队列做维护
代码实现
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=300010;
int q[N];
LL s[N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;
cin>>x;
s[i]=s[i-1]+x;
}
int hh=0,tt=0;
q[0]=0;
LL res=INT_MIN;
for(int i=1;i<=n;i++){
if(hh<=tt && i-q[hh]>m)
hh++;
//注意这个位置 当前数的左边最小值 应该是不包含该数的左边m个数里找(在队头) 所以在插入之前更新答案
res=max(s[i]-s[q[hh]],res);
while(hh<=tt && s[i]<=s[q[tt]])
tt--;
q[++tt]=i;
}
cout<<res<<endl;
return 0;
}
💬 评论