题意:给出n个数的循环序列,要求长度不超过k的连续子序列之和的最大值。
分析:单调队列求解。单调队列就是有单调性的队列,可以从两端删除元素,但还是只能从 队尾添加元素。可以认为这种队列前面存的是过期的值,后面存的是还有用的 值。
单调队列一般用来求解固定区间长度内的最大值或区间内元素之和的最大值。
对本题而言,由于是环,要补足2*n个数(其实n+k-1个就够了),求出前i个数字之和sum[i],0<i<2*n。题目实际所求的就是max(sum[j]-sum[i]),j-i<k,那么 就需要求 出min(sum[i])。枚举每一个区间尾i,并用一个单调递增队列保存区间内sum[i]值的下标,则对每一个区间尾i,有最优区间头q[head],于是sum[i]-sum[a[head]-1]就是 区间(q[head],i)内元素和的最大值。
那么如何保证区间头q[head]是最优值呢?这就要靠删除队尾了。我们知道,对每一个队尾元素,都可能是以后某个有最大和的区间的起始下标,因此, 当我们要把一 个区间尾i插入队尾时,sum[i-1]-sum[q[tail-1]-1]表示(q[tail-1],i-1)这个区间 的 和,如果这个值小于0,那么就说明以q[tail-1]为区间头会导致和变小,于是将其删去。 这样就保证了q[head]是最优区间头。
分析:单调队列求解。单调队列就是有单调性的队列,可以从两端删除元素,但还是只能从 队尾添加元素。可以认为这种队列前面存的是过期的值,后面存的是还有用的 值。
单调队列一般用来求解固定区间长度内的最大值或区间内元素之和的最大值。
对本题而言,由于是环,要补足2*n个数(其实n+k-1个就够了),求出前i个数字之和sum[i],0<i<2*n。题目实际所求的就是max(sum[j]-sum[i]),j-i<k,那么 就需要求 出min(sum[i])。枚举每一个区间尾i,并用一个单调递增队列保存区间内sum[i]值的下标,则对每一个区间尾i,有最优区间头q[head],于是sum[i]-sum[a[head]-1]就是 区间(q[head],i)内元素和的最大值。
那么如何保证区间头q[head]是最优值呢?这就要靠删除队尾了。我们知道,对每一个队尾元素,都可能是以后某个有最大和的区间的起始下标,因此, 当我们要把一 个区间尾i插入队尾时,sum[i-1]-sum[q[tail-1]-1]表示(q[tail-1],i-1)这个区间 的 和,如果这个值小于0,那么就说明以q[tail-1]为区间头会导致和变小,于是将其删去。 这样就保证了q[head]是最优区间头。
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
const int M=1010;
const int N=1000005;
const int INF=1e9;
int n,k,q[N],sum[N];
int main()
{
int i,j,t;
cin>>t;
while(t--)
{
scanf("%d%d",&n,&k);
for (i=1;i<=n;i++){
scanf("%d",sum+i);
sum[i+n]=sum[i];
}
int m=n+k-1;
for (i=1;i<=m;i++) {
sum[i]+=sum[i-1];
}
int head=0,tail=0,Max=-INF,a,b;
for (i=1;i<=m;i++){
while(head<tail && sum[q[tail-1]-1]>sum[i-1]) tail--; // sum[i]-sum[q[tail-1]-1] 表示 sum(q[tail-1],i-1) 这个区间内的和,若这个和小于0,那么就不能以q[tail-1]为区间头,将其删去。这样可以保证单调队列的队头是最优区间头q[head]
q[tail++]=i;
while(head<tail && i-q[head]>=k) head++; // 超出区间则删去队头
if (sum[i]-sum[q[head]-1]>Max){ //cout<<sum[i]<<" "<<sum[q[head]-1]<<endl;
Max=sum[i]-sum[q[head]-1];
a=q[head]; b=i; // printf("%d %d %d\n",Max,a,b);
}
}
printf("%d %d %d\n",Max,a,b>n?b-n:b);
}
}