其他分享
首页 > 其他分享> > 最大子序和(单调队列)

最大子序和(单调队列)

作者:互联网

题目:

见https://www.acwing.com/problem/content/137/

思路:

1.先考虑前缀和,也就是要对于每个i在其前i-m个数里找到一个最小的数,即可保证终点为i长度不超过m的子序列和最大。
2.对于这i-m个数,我们采用队列来维护,并且这个队列一定具有单调递增的特性,因为如果该队列新进来的元素比队尾元素的值要大,那么该尾部元素就肯定不会被选中,所以我们一直删除队尾元素,直到队尾元素的值小于新进元素。
3.本题代码采用数组实现队列,且该队列中存放的元素是数的编号而不是数本身,然后注意用两个变量来表示队列队头和队尾

代码:

#include<iostream>
#include<algorithm>
#include<climits>
using namespace std;
const int N=3e5+10;
int a[N];
int res=INT_MIN;
int q[N];
int t,h;//t是队尾,h是队头,用数组模拟队列
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        a[i]+=a[i-1];//计算前缀和
    }
    for(int i=1;i<=n;i++)
    {
        if(q[h]<i-m) h++;//维护单调队列
        res=max(res,a[i]-a[q[h]]);
        while(h<=t&&a[q[t]]>=a[i]) t--;//维护单调队列
        q[++t]=i;
    }
    cout<<res<<endl;
    return 0;
}

标签:队尾,队列,元素,int,include,子序,单调
来源: https://blog.csdn.net/qq_45736714/article/details/114983962