1302: 最大子序列
时间限制: 1 Sec 内存限制: 128 MB提交: 224 解决: 54
[ 提交][ 状态][ 讨论版]
题目描述
给定一个N个整数组成的序列,整数有正有负,找出两段不重叠的连续子序列,使得它们中整数的和最大。两段子序列都可以为空。
输入
多组输入,每组第一行为N,表示序列的长度;第二行为N个整数(-1000<=n<=1000),表示输入序列。
0<N<=1,000,000
输出
对于每组输入,输出一行,仅一个整数,表示最大的和。
样例输入
9
185 -580 -889 701 964 -878 353 -761 608
样例输出
2273
第一步,求出最大子序列M;M表示max
第二步,求出不与M相交的第二大子序列S;S表示second
第三步,求出M中的最小子序列L;L表示little
最后,分两种情况:M+S或者是M一分为二;
若S+L<0,说明L太小了,M应该舍弃L,一分为二;
否则,M+=S;
#include<iostream>
using namespace std;
int a[1000007];
int m[1000007];
int from, to;
int M, S, L;
int n;
void init(){
int i;
M = 0;
m[0] = a[0];
int f, t;
f = t = 0;
for (i = 1; i < n; i++)
{
if (m[i - 1]>0){
m[i] = m[i - 1] + a[i];
t++;
}
else{
f = t = i;
m[i] = a[i];
}
if (M < m[i]){
M = m[i];
from = f;
to = t;
}
}
}
void getS(){
int i;
int mm = 0;
for (i = 0; i < from; i++){
if (m[i]>mm)
mm = m[i];
}
int now = a[to + 1];
for (i = to + 2; i < n; i++){
if (now>0){
now += a[i];
}
else{
now = a[i];
}
if (now > mm)mm = now;
}
S = mm;
}
void getL(){
int i;
int ll = a[from];
int now = a[from];
for (i = from + 1; i < to + 1; i++){
if (now<0){
now += a[i];
}
else{
now = a[i];
}
if (now < ll)ll = now;
}
L = ll;
}
int main(){
freopen("in.txt", "r", stdin);
while (scanf("%d", &n) != -1){
int i;
for (i = 0; i < n; i++){
scanf("%d", &a[i]);
}
init();
getS();
getL();
if (S + L < 0){
M -= L;
}
else{
M += S;
}
printf("%d\n", M);
}
return 0;
}