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时,将队首元素删除。
代码如下:

#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; }