单调栈(仅限于理解)

给你一个n数组 让你找出  (m以内)子序列 的最大值;

我们选择前缀和先来处理一波

最暴力写法o(nm)

ans = s[1];
for(int i=1 ;i<=n;i++){
	int mi = 99999999;
	for( int j=i-m;j<i;j++)
        if(j>=0) mi = min(mi,s[j]);
    ans = max(ans,s[i]-mi);
}
printf("ans=%d\n",ans);

优化  单调队列 时间复杂度o(n)
 单调队列的操作:
1. 队头出队:head++
2.队尾入队:++tail
        1.直接插入:++tail
        2.先删后插:tail--,++tail
 

int t = 0 , h = 0;
q[0] = 0 , ans = s[1];
for(int i= 1;i<=n;i++){
    //q[h]不在窗口{i-m,i-1}内,队头出列 
    if(h<=t && q[h]<i-m) h++;
    //使用队头最小值
    ans = max(ans,s[i]-s[q[h]]);
    //当前值<=队尾值,队尾出列	
    while(h<=t &&  s[i]<=s[q[t]]) t--;
    // 下标入队,便于对队头出队
    q[++t]=i;
}
printf(" ans=%d\n",ans);

完整代码

#include "bits/stdc++.h"

using namespace std;
int s[105],q[105];
int n,m;
int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;i++){
        cin >> s[i];
        s[i] = s[i]+s[i-1];
    }
    int head = 0 , tail = 0 , ans = s[1];
    q[0]=0;
    for(int i=1 ; i<=n ;i++){
        if(head <= tail && q[head] < i-m) head++;
        ans = max(ans,s[i] - s[q[tail]]);
        while (head <= tail && s[i] <= s[q[tail]]) tail--;
        q[++tail]=i;
    }
    cout << ans << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_53013914/article/details/121145809
Recommended