Maximum sum
Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
Your task is to calculate d(A).
Input
The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input.
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.
Output
Print exactly one line for each test case. The line should contain the integer d(A).
Sample Input
1
10
1 -1 2 2 3 -3 4 -4 5 -5
Sample Output
13
Hint
In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer.
Huge input,scanf is recommended.
Source
POJ Contest,Author:Mathematica@ZSU
题目类型:最大连续子序列和
算法分析:假设所求两个子序列最大和为sum,两个子序列分别为left和right,这两个子段一个在序列的左边,一个在右边。那么在它们中间必定有一个分割点(这个点即可能被包含在其中一个子段中,也可能不)。设这个点为k,那么left必定是从0到k这个子段的最大子序列(用反证法证明,假设存在在0到k这个范围内的一个子序列nleft的比left大,那么nleft+right将大于sum,这就与上面假设最和为sum矛盾,所以必定不成立比left大的nleft)
,right必定是从k+1到n-1(n为序列长度)这个子段的最大子序列(证明过程同上),那么我们现在的问题就转换成了求两个最大子序列。我们从左边开始,往右边求出每个点的最大左子段和,保存在Left数组中,然后再从右边开始,往左边求出每个点的最大右子段和,然后再遍历每个点,求出每个点的两个最大左右子段和,即可得出答案。
注意:由于求最大子序列和的全局最优解需要遍历一下数组dp,这里使用就地滚动来将dp[i-1]的最优解和dp[i]处的最优解进行比较,选取更优的存储在dp[i]中,则此时dp[i]数组中存储的是前i个数组成的最大子序列和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
#include <set> #include <bitset> #include <list> #include <map> #include <stack> #include <queue> #include <deque> #include <string> #include <vector> #include <ios> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <algorithm> #include <utility> #include <complex> #include <numeric> #include <functional> #include <cmath> #include <ctime> #include <climits> #include <cstdarg> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cassert> using namespace std; const int INF = 0x7FFFFFFF; const int MOD = 1000000000 + 7; const double EPS = 1e-10; const double PI = 2 * acos (0.0); const int maxn = 100000 + 66; int Left[maxn], Right[maxn], ans[maxn]; int main() { freopen ("aaa.txt", "r", stdin); int t; scanf ("%d", &t); while (t--) { int n; scanf ("%d", &n); for (int i = 1; i <= n; i++) scanf ("%d", &ans[i]); Left[1] = ans[1]; for (int i = 2; i <= n - 1; i++) Left[i] = max (Left[i-1] + ans[i], ans[i]); for (int i = 2; i <= n - 1; i++) Left[i] = max (Left[i], Left[i-1]); Right[n] = ans[n]; for (int i = n - 1; i >= 1; i--) Right[i] = max (Right[i+1] + ans[i], ans[i]); for (int i = n - 1; i >= 1; i--) Right[i] = max (Right[i], Right[i+1]); int maxval = -INF; for (int i = 1; i <= n - 1; i++) { maxval = max (maxval, Left[i] + Right[i+1]); } printf ("%d\n", maxval); } return 0; } |
- « 上一篇:poj2478
- poj2480:下一篇 »