您的位置:首页 > 其它

BIT 1011 Maximum Sum II

2013-02-18 21:23 211 查看
题目大意:给出n(n<=50000)个数,求出长度不超过k(k<=50000)的最大连续子序列和。

考察点:单调队列

思路分析:要求长度不超过k的最大连续子序列和,就是求max(s[j]-s[i]),j-i>k,也就是对于每个j,我们要找出最小的i,进而求出在j之前最大的和。那么如何找i呢,就需要用单调队列了。

单调队列即保持队列中的元素单调递增(或递减)的这样一个队列,可以从两头删除,只能从队尾插入。单调队列的具体作用在于,由于保持队列中的元素满足单调性,对于上述问题中的每个j,可以用O(1)的时间找到对应的s[i]。(保持队列中的元素单调递增的话)

具体做法:我们开一个队列来记录s[j]的标号j,当我们要插入一个新的s[j]的时候,我们从队列尾开始往前删除元素,直到遇到一个比它小的。因为这些被删除的元素序号比它小,值还比它大,s[j]-s[i]时它肯定不是最优的i,所以可以删掉。

当我们从队首取元素时,要保证j-s[head]<k,否则的话就继续往前扫。

接下来是代码:

#include<stdio.h>

int s[50050],q[1000000];
int main()
{
int t,n,k,i,max;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&k);
for (i=1;i<=n;i++)
{
scanf("%d",&s[i]);
s[i]+=s[i-1];
}
max=-100000000;
int head=0,tail=0;
for (i=1;i<=n;i++)
{
while ((head<tail)&&(s[i-1]<=s[q[tail-1]])) tail--;
q[tail]=i-1;tail++;
while ((head<tail)&&(i-q[head]>k)) head++;
if (max<s[i]-s[q[head]])
max=s[i]-s[q[head]];
}
printf("%d\n",max);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: