HLG 1522 子序列的和【队列的应用】

Description
输入一个长度为n的整数序列(A1,A2,……,An),从中找出一段连续的长度不超过m的子序列,使得这个子序列的和最大。
Input
有多组测试数据,不超过20组测试数据
对于每组测试的第一行,包含两个整数n和m(n,m<=10^5),表示有n个数,子序列长度限制为m,表示这个序列的长度,第二行为n个数,每个数的范围为[-1000, 1000]。
 
Output
对于每组测试数据,输出最大的子序列和,并换行。
Sample Input
3 1
1 2 3
3 2
-1000 1000 1
Sample Output
3
1001 

思路:看的比较懂得参考资料:http://blog.csdn.net/Justmeh/article/details/5844650 

   在复制一下里面比较重要的话:

1.首先看插入元素:为了保证队列的递减性,我们在插入元素v的时候,要将队尾的元素和v比较,如果队尾的元素不大于v,则删除队尾的元素,然后继续将新的队尾的元素与v比较,直到队尾的元素大于v,这个时候我们才将v插入到队尾。

 

2.队尾的删除刚刚已经说了,那么队首的元素什么时候删除呢?由于我们只需要保存i的前k-1个元素中的最大值,所以当队首的元素的索引或下标小于i-k+1的时候,就说明队首的元素对于求f(i)已经没有意义了,因为它已经不在窗里面了。所以当index[队首元素]<i-k+1时,将队首元素删除。

 

代码如下:

View Code
#include<stdio.h>

#include<string.h> 

#define INF 999999999 

int sum[100005], p[100005]; 

int main()

{

    int i, j, n, m, a;

    while(scanf("%d%d", &n, &m)!=EOF)

    {

        memset(sum, 0, sizeof(sum));

        memset(p, 0, sizeof(p)); 

        for(i=1; i<=n; i++)

        {

            scanf("%d", &a);

            sum[i]=sum[i-1]+a;

        }

        int beg=0, end=0, maxnum=-INF; 

        for(i=1; i<=n; i++)

        {

             while(p[beg]<i-m)    

                 beg++;

             while(sum[p[end]]>=sum[i]&&end>=beg)

                 end--;

              end++; 

             if(sum[i]-sum[p[beg]]>maxnum)

                 maxnum=sum[i]-sum[p[beg]];

             p[end]=i;

        }

        printf("%d\n", maxnum);

    }

    return 0;

} 

 

 

 

你可能感兴趣的:(队列)