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; }