poj 2479 最大连续子段和

容易想到:对于每个i,求出最大的第一个子段在区间[0,i]内和最大的第二个子段在区间[i+1,n-1]内再相加即可。

对于第一个子段的求法:

令p[i]表示以i结尾的子段的最大连续子段和,则显然有:

  p[i] = max( a[i], a[i] + p[i - 1] );

  求完以后再:

  p[i] = max( p[i], p[i - 1] );

  就可以得到含于区间[0,i]的最大子段和。

对于第二个子段的求法:

其实就是用这个方法再倒着求一遍。

最后求出答案即可。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 const int N = 50000;
 7 const int INF = -999999999;
 8 int a[N], p[N], q[N];
 9 
10 int main ()
11 {
12     int t;
13     scanf("%d", &t);
14     while ( t-- )
15     {
16         int n;
17         scanf("%d", &n);
18         for ( int i = 0; i < n; i++ ) scanf("%d", a + i);
19         p[0] = a[0];
20         for ( int i = 1; i < n; i++ )
21         {
22             p[i] = a[i];
23             if( p[i - 1] > 0 )
24             {
25                 p[i] += p[i - 1];
26             }
27         }
28         for ( int i = 1; i < n; i++ )
29         {
30             p[i] = max( p[i], p[i - 1] );
31         }
32         q[n - 1] = a[n - 1];
33         for ( int i = n - 2; i >= 0; i-- )
34         {
35             q[i] = a[i];
36             if( q[i + 1] > 0 )
37             {
38                 q[i] += q[i + 1];
39             }
40         }
41         for ( int i = n - 2; i >= 0; i-- )
42         {
43             q[i] = max( q[i], q[i + 1] );
44         }
45         int ans = INF;
46         for ( int i = 0; i < n - 1; i++ )
47         {
48             ans = max( ans, p[i] + q[i + 1] );
49         }
50         printf("%d
", ans);
51     }
52     return 0;
53 }
原文地址:https://www.cnblogs.com/huoxiayu/p/4644642.html