Max Sum Plus Plus m段连续子序列最大和

时间:2021-12-28 18:44:17
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.

Given a consecutive number sequence S1, S2, S3, S4 ... Sx, ... Sn (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ Sx ≤ 32767). We define a function sum(i, j) = Si + ... + Sj (1 ≤ i ≤ j ≤ n).

Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i1, j1) + sum(i2, j2) + sum(i3, j3) + ... + sum(im, jm) maximal (ix ≤ iy ≤ jx or ix ≤ jy ≤ jx is not allowed).

But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(ix, jx)(1 ≤ x ≤ m) instead. ^_^
 
Input Each test case will begin with two integers m and n, followed by n integers S1, S2, S3 ... Sn.
Process to the end of file.
 
Output Output the maximal summation described above in one line.
 
Sample Input
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
 
Sample Output
6
8


算是最大连续子序列和的加强版吧

状态:dp[i][j]表示前j个元素组成i组子序列和的最大值

状态转移:dp[i][j] = max(dp[i][j-1], max(dp[i-1][k])) + a[j] ,注意这里 i-1 <= k >= j-1

但是 j <= n <= 10000000,而且m的范围不知道,所以很有可能超内存...

看了网上的做法,说用什么滚动数组?记录前一组的最大值,所以是不断更新的

#include <iostream>  
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
const int N = 1e6 + 3;

int dp[N], a[N], pre[N]; //pre数组记录前一段和的最大值

int main()
{
int m, n;
while(~scanf("%d%d", &m, &n))
{
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
memset(pre, 0, sizeof(pre));
dp[0] = 0;
int p;
for(int i = 1; i <= m; i++)
{
p = -1e9;
for(int j = i; j <= n; j++) //这里j一定要从i开始,因为每一组的元素数量肯定至少是1...
{
dp[j] = max(dp[j-1], pre[j-1]) + a[j];
pre[j-1] = p; //记录下来,为i+1组使用,使用后更新,为下一组使用
p = max(p, dp[j]);
}
}
printf("%d\n", p);
}
return 0;
}