最大子序和(单调队列优化)
2015-01-16 18:07
218 查看
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
input
第一行:n,m
第二行:n个数
output
最大的和sum
题目分析:首先我们知道O(n)可以很简单的解决原题(不限制子序列的长度)。但是这题加了限制(长度不超过m),并且数据为300000,并不能用O(n*m)的暴力计算最大前缀和之差的方法。所以要用到一些特殊的姿势~~~单调队列。
首先我们分析知道 f[i]=max(sum[i]-s[i-k]),k∈[1,m]。但是一般的维护只能是O(n*m)。变成f[i]=sum[i]-min(sum[i-k]),k∈[1,m]。我们只需要维护一个宽度为m的范围内的sum值的队列,然后每次用最小的去更新f[i],再将sum[i]也加入队列。用优先队列的思想,每个sum最多只能进一次队列出一次队列,所以复杂度是O(2*n)。
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
input
第一行:n,m
第二行:n个数
output
最大的和sum
题目分析:首先我们知道O(n)可以很简单的解决原题(不限制子序列的长度)。但是这题加了限制(长度不超过m),并且数据为300000,并不能用O(n*m)的暴力计算最大前缀和之差的方法。所以要用到一些特殊的姿势~~~单调队列。
首先我们分析知道 f[i]=max(sum[i]-s[i-k]),k∈[1,m]。但是一般的维护只能是O(n*m)。变成f[i]=sum[i]-min(sum[i-k]),k∈[1,m]。我们只需要维护一个宽度为m的范围内的sum值的队列,然后每次用最小的去更新f[i],再将sum[i]也加入队列。用优先队列的思想,每个sum最多只能进一次队列出一次队列,所以复杂度是O(2*n)。
#include<iostream> #include <bits/stdc++.h> using namespace std; int a[300100]; long long s[300100],f[300100],x[300100],w[300100]; int main() { int i,n,m,l,r; long long ans=0; scanf("%d%d", &n, &m); memset(f,0,sizeof(f)); memset(s,0,sizeof(s)); for (i=1;i<=n;i++) { scanf("%d", &a[i]);s[i]=s[i-1]+a[i]; } l=1;r=1;x[1]=0;w[1]=0; for (i=1;i<=n;i++) { while (w[l]<i-m) l++; f[i]=s[i]-s[w[l]]; while (s[i]<x[r]&&r>=l) r--; r++; x[r]=s[i];w[r]=i; } for (i=1;i<=n;i++) if (f[i]>ans) ans=f[i]; printf("%I64d\n", ans); return 0; }
相关文章推荐
- tyvj1305 最大子序和 【单调队列优化dp】
- tyvj1305 最大子序和 【单调队列优化dp】
- Tyvj1305最大子序和(单调队列优化dp)
- 【动态规划】【单调队列】tyvj1305 最大子序和
- HDU1024 最大M子段和问题 (单调队列优化)
- HDU2870 最大窗口面积(单调队列优化)
- UVaLive LA 4726 UVa 1451 - Average (子序列最大平均数 数形结合 斜率优化 单调队列)
- TYVJ1305 最大子序和 - 单调队列
- HDU1081 最大字段和 压缩数组(单调队列优化)
- hdu 2870 最大子矩阵 单调队列优化+dp
- 线性 dp问题の 单调队列优化
- 单调队列优化DP能到什么程度(今天中午进行的实验记录)
- 单调队列+IO优化 POJ——Sliding Window
- CDOJ1696 吴神的炒股技巧 [dp + 单调队列优化]
- FOJ 1914. Funny Positive Sequence 【单调队列优化】
- 【专辑】单调队列+斜率优化的DP
- POJ 1742:Coins——单调队列优化的多重背包
- 【二维单调队列】FZU- Problem 2080 最大差值
- pku3709 dp单调队列优化
- HDU OJ 1506 Largest Rectangle in a Histogram 和 NYOJ 258 最大长方形(二) 【单调队列】