题目描述
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
输入格式
第一行两个数n,m
第二行有n个数,要求在n个数找到最大子序和
输出格式
一个数,数出他们的最大子序和
提示
数据范围:
100%满足n,m<=300000
样例数据
输入样例 #1 | 输出样例 #1 |
---|---|
6 4 1 -3 5 1 -2 3 | 7 |
本题我们要找一个不超过M长度的和最大的子段(可以不取)。那么直接把所有前缀和求出来,For一遍每一个右端点,用单调队列维护一下前面m个以内最小的前缀和是多少就行了
Code:
#include<cstdio> #include<algorithm> using namespace std; const int maxn = 1e6 + 5; int q[maxn][2], f = 1, b = 0, n, m, sum[maxn], mx = 0; void push(int i, int x) { while(q[b][1] >= x && f <= b) --b; q[++b][0] = i, q[b][1] = x; if(q[f][0] <= i - m) ++f; } int main() { scanf("%d%d", &n, &m); for(register int i = 1; i <= n; ++i) scanf("%d", &sum[i]); for(register int i = 2; i <= n; ++i) sum[i] += sum[i - 1]; for(register int i = 1; i <= n; ++i) mx = max(mx, sum[i] - q[f][1]), push(i, sum[i]); printf("%d", mx); return 0; }
没有帐号? 立即注册