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.
一道簡單的子區間最大和問題。作一個小小的轉化:題目中要求兩個子序列,且它們的和最大,則轉化為求前綴子序列和後綴子序列最大,這樣求兩次最大子序列就可以將問題解決了。
Accode:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <bitset>
using std::max;
using std::min;
const char fi[] = "poj2479.in";
const char fo[] = "poj2479.out";
const int maxN = 50010;
const int MAX = 0x3fffff00;
const int MIN = -MAX;
int data[maxN];
int f1[maxN], f2[maxN];
int n, N;
void init_file()
{
freopen(fi, "r", stdin);
freopen(fo, "w", stdout);
}
void work()
{
int tmp = data[1];
f1[1] = data[1];
for (int i = 2; i < n + 1; ++i)
{
tmp = max(tmp, 0);
f1[i] = tmp += data[i];
f1[i] = max(f1[i], f1[i - 1]);
}
f2[n] = tmp = data[n];
for (int i = n - 1; i > 0; --i)
{
tmp = max(tmp, 0);
f2[i] = tmp += data[i];
f2[i] = max(f2[i], f2[i + 1]);
}
}
void readdata()
{
scanf("%d", &N);
for (int t = 0; t < N; ++t)
{
memset(f1, 0, sizeof(f1));
memset(f2, 0, sizeof(f2));
scanf("%d", &n);
for (int i = 1; i < n + 1; ++i)
scanf("%d", data + i);
work();
int ans = MIN;
for (int i = 1; i < n; ++i)
ans = max(ans, f1[i] + f2[i + 1]);
printf("%d\n", ans);
}
}
int main()
{
init_file();
readdata();
exit(0);
}