-
总Time Limit:
- 1000ms Memory Limit:
- 65536kB
-
Description
-
Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
t1 t2
d(A) = max{ ∑ai + ∑aj | 1 <= s1 <= t1 < s2 <= t2 <= n }
i=s1 j=s2
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 -
-
思路:定义两个数组:left[100000]和right[100000];分别存从左往右,和从右往左的子串的最大值;即:a[0], a[1], a[2],.....a[n],
left[i]表示:在 0 到 n 之间的最大和子串的值;right[i]表示:i到n 之间的最大和子串的值。 -
求left[i]的方法与求right[i]的方法类似,这里给求left[i]的方法。采用dp思想:先知道left[0] = a[0] ,定义一个current = a[0],根据current求出a[1]时curent的值,即current在更换值;而current代表以i为一个终点,它(包含它)之前的最大和子串。if (current <0), 那么current = a[i];else current += a[i]。再判断left[i-1]与current的大小,如果前者小,则,left[i] = current;否则,left = left[i-1]; -
计算 完left和rihgt后,再得到answer 为 left[i]+right[i+1]里中最大的一个。 -
- 以题目给的数据举例:
-
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]; -
1 -1 2 2 3 -3 4 -4 5 -5 -
-
current(left)
1 0 2 4 7 4 8 4 9 4 -
left[i]
1 1 2 4 7 7 8 8 9 9 -
-
currebt(right)
9 8 9 7 5 2 5 1 5 -5 -
right[i]
9 9 9 7 5 5 5 5 5 -5 -
-
-
-
-
C语言:
ac代码 #include
inta[ 100000];
intleft[ 100000] = { 0}; //从左往右时,以这个点为终点,在它前面的子串里面的和最大值;
intright[ 100000] = { 0}; //从右往左时,以这个点为终点,在它前面的子串里面的和最大值;
intmain()
{
int T, n, i;
int current;
int answer;
scanf( "%d", &T);
while (T--)
{
scanf( "%d", &n);
for (i= 0; i
{
scanf( "%d", &a[i]);
}
//计算左边的子串最大值;
current = left[ 0] = a[ 0];
for(i= 1; i
{
left[i] = left[i- 1];
if(current < 0)
current = a[i];
else
current = current + a[i];
if(current > left[i- 1])
left[i] = current;
}
//计算右边的子串的最大值;
current = right[n- 1] = a[n- 1];
for(i=n- 2; i>= 0; i--)
{
right[i] = right[i+ 1];
if(current < 0)
current = a[i];
else
current = current + a[i];
if(current > right[i+ 1])
right[i] = current;
}
//找到左右和的最大值;
answer = left[ 0] + right[ 1];
for(i= 1; i1; i++)
{
if(answer < (left[i]+right[i+ 1]))
answer = left[i]+right[i+ 1];
}
printf( "%d \n ", answer);
}
return 0;
} -
-
-
-
-
-
-
-
-
-