一本通 最大连续和

写下单调队列思路怕自己忘

计算区间和的问题,一般转换为两个前缀和相减,所以我们先求出前缀和sum[i]表示前i项的和,那么就转化成了求 $s[r]-s[l-1]$

枚举右端点,则问题变为:找到一个左端点, $im<=j<=i1$ 且 $s[j]$ 最小

然后执行单调队列的几个步骤:

  1. 判断队首与i的距离是否超过M的范围,若超出则弹

  2. 更新答案,因为此时队首就是右端点为i时,左端点j最佳选择

  3. 不断删除队尾,直到队尾的sum小于sum[i],然后将i入队

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define re register int
    #define ll long long
    #define maxn 300005
    using namespace std;
    int a[maxn], q[maxn], sum[maxn];
    int l, r;
    int n, m;
    int main() {
        scanf("%d%d", &n, &m);
        for (re i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i];
        l = 1, r = 1;
        q[1] = 0;
        int ans = -0x3f3f3f3f;
        for (re 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;
    }

     

posted @ 2019-08-12 13:40  红色OI再临  阅读(170)  评论(0编辑  收藏  举报