AcWing 135. 最大子序和

AcWing 135. 最大子序和

思路

  • 计算区间和问题一般转化成前缀和问题,所以原问题可以转化成找出两个位置 l l l r r r 使得 a [ r ] − a [ l − 1 ] a[r]-a[l-1] a[r]a[l1]最大并且 r − l + 1 < = m r-l+1 <= m rl+1<=m
  • 首先我们枚举 i i i,当 i i i固定为右端点时,问题就转化成找一个左端点 j j j j j j 范围为 [ i − m + 1 , i − 1 ] [i-m+1,i-1] [im+1,i1],并且 a [ j − 1 ] a[j-1] a[j1] 最小(因为要使得 i i i j j j 的和 a [ i ] − a [ j − 1 ] a[i]-a[j-1] a[i]a[j1]最大)。
  • 这时就容易想到单调队列( q u e que que 为下标的队列):当队尾的值 a [ q u e [ t − 1 ] ] a[que[t-1]] a[que[t1]] 大于等于 a [ i ] a[i] a[i] 时完全可以把队尾弹出,因为i下标更大(更不容易被淘汰)且值更小。那么队头的值就会一定是最小的,这里要注意的是,右端点更新时要判断一下是否弹出队头(保持 i − q u e [ t − 1 ] + 1 < = m i-que[t-1]+1 <= m ique[t1]+1<=m )。
#include<iostream>
#define int long long
using namespace std;
const int N = 300010;
int a[N],que[N],h,t;
signed main(){
    int n,m; cin>>n>>m;
    for(int i = 1; i <= n; i++) {
        int x; cin>>x;
        a[i] = a[i-1] + x;
    }
    int res = -0x3f3f3f3f;
    h = 0,t = 1;
    for(int i = 1; i <= n; i++){
        if(h < t && i - que[h] > m) h++;
        res = max(res, a[i] - a[que[h]]);
        while(h < t && a[que[t-1]] >= a[i]) t--;
        que[t++] = i;
    }
    cout<<res;
    return 0;
}
参考

https://www.acwing.com/solution/content/28015/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值