给你一个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;
}