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

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号