Problem Description
给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
注意:本题目要求用分治递归法求解,除了需要输出最大子段和的值之外,还需要输出求得该结果所需的递归调用总次数.
Input
第一行输入整数n(1<=n<=50000),表示整数序列中的数据元素个数;
第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。
Output
一行输出两个整数,之间以空格间隔输出:
第一个整数为所求的最大子段和;
第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。
Example Input
6 -2 11 -4 13 -5 -2
Example Output
20 11
#include <algorithm> #include <cstdio> using namespace std; int cnt; typedef struct { int *elem; int length; } sqlist; void initial(sqlist &l, int n) { l.elem = (int *)malloc(n * sizeof(int)); l.length = 0; } void create(sqlist &l, int n) { int i; for (i = 0; i < n; i++) { scanf("%d", &l.elem[i]); } l.length = n; } int maxsum(sqlist l,int le, int r) { int sum = 0; cnt++; if(le==r) { if(l.elem[le]>=0)sum =l.elem[le]; else sum = 0; } else { int mid = (le+r)/2; int leftsum = maxsum(l,le, mid); int rightsum = maxsum(l,mid+1, r); int s1, s2, ss; s1 = ss = 0; for(int i = mid; i>=le; --i) { ss+=l.elem[i]; if(ss>s1)s1 = ss; } s2 = ss = 0; for(int i = mid+1; i<=r; ++i) { ss+=l.elem[i]; if(ss>s2)s2 = ss; } sum = s1+s2; sum = max(sum, leftsum); sum = max(sum, rightsum); } return sum; } int main() { int n,maxx; scanf("%d",&n); sqlist l; initial(l, n); create(l, n); cnt = 0; maxx = maxsum(l,0, n-1); printf("%d %d\n", maxx, cnt); return 0; }