题目描述
输入一个长度为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;
}
rockdu
没有帐号? 立即注册