滑动窗口可以维护一串数列的单调性,也可以看作是单调栈(我觉得),具体刘汝佳的书上有写。
例题为Uva1619,单调栈+滑动窗口
题意:求一连续数列中 ,一段连续子序列a1到an 使(a1+ ... +an) * min(a1,...,an) 最大
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <cstdio>
#include <cstring>
const int maxn = 100000 + 5;
using namespace std;
int l[maxn],r[maxn];
long long sum[maxn];
long long num[maxn];
int n;
void solve()
{
int left = 1,right = 1;
long long ans = 0;
for(int i=1; i<=n; i++)
{
long long temp = num[i] * ( sum[r[i]] - sum[l[i] - 1]);
if(temp > ans || (temp == ans && (right - left > r[i] - l[i])))
{
ans = temp;
right = r[i];
left = l[i];
}
}
printf("%lld\n%d %d\n",ans,left,right);
}
int main()
{
int case_ = 0;
while(scanf("%d",&n)!=EOF && n)
{
memset(num,-1,sizeof(num)); //这句话没有是错的
for(int i=1; i<=n; i++)
{
scanf("%lld",&num[i]);
sum[i] = num[i] + sum[i-1];
l[i] = i;
r[i] = i;
}
for(int i=1; i<=n; i++) //更新每一个数左边维护的值
{
while(num[l[i] - 1] >= num[i])
{
l[i] = l[l[i] - 1]; //下标
}
}
for(int i=n; i>=1; i--)
{
while(num[r[i] + 1] >= num[i])
{
r[i] = r[r[i] + 1];
}
}
if(case_) printf("\n");
case_++;
solve();
}
return 0;
}