/*DSA*/#include<algorithm> /*DSA*/usingnamespace std; /*DSA*/externint s_lo, s_hi; /*DSA*/ intgs_DC( int A[], int lo, int hi ){ //分治策略:O(n*logn) if ( hi - lo < 2 ) return A[lo]; int mi = (lo + hi) / 2; int gsL = 0, gsR = 0; //前缀|后缀中的最大后缀|前缀 for ( int s = 0, i = mi-1; lo <= i; i-- ) //枚举[lo,mi)的所有后缀 gsL = max(gsL, s += A[i]); //择优更新 for ( int s = 0, j = mi; j < hi; j++ ) //枚举[mi,hi)的所有前缀 gsR = max(gsR, s += A[j]); //择优更新 returnmax( gsL + gsR, max( gs_DC( A, lo, mi ), gs_DC( A, mi, hi ) ) ); //递归 } //gs_DC
S [k,n)<0:任何以 n 为终点跨越 k 的序列不可能是 GS
S [k,n)>0:k 不可能是 GS 的终点,否则可以加上这段后缀变得更大
在 gs 可以被更新的时候更新一下左右区间,sum < 0 的时候改右边界,左边界随循环改变就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*DSA*/#include<algorithm> /*DSA*/usingnamespace std; /*DSA*/externint s_lo, s_hi; /*DSA*/ intgs_LS( int A[], int n ){ //减治策略:O(n) int gs = 0; //目前已知的最大和 = S[n,n) = 0 /*DSA*/s_lo = n; s_hi = n; for ( int sum = 0, k = n-1; 0 <= k; k-- ) { //当前区间[k,n) sum += A[k]; //递增地更新后缀和 /*DSA*/if ( gs < sum ) { s_lo = k; s_hi = n; } /*DSA*/if ( sum <= 0 ) { n = k; } gs = max( gs, sum ); //择优更新 sum = max( sum, 0 ); //剪除总和非正的后缀 } //for return gs; } //gs_LS