总时间限制: 1000ms
内存限制:
65536kB
描述
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).
输入
The input consists of T(<=30) testcases. The number of test cases (T) is given in the first line of theinput. Each test case contains two lines. The first line is an integern(2<=n<=50000). The second line contains n integers: a1, a2, ..., an.(|ai| <= 10000).There is an empty line after each case.
输出
Print exactly one line for each testcase. The line should contain the integer d(A).
样例输入
1
10
1 -1 2 2 3 -3 4 -4 5 -5
样例输出
13
提示
In the sample, we choose {2,2,3,-3,4}and {5}, then we can get the answer.Huge input,scanf is recommended
题意:给定一个数组,求两个不相交的连续子序列,使得其和最大。
分析:首先,对于一个序列,要求得一个连续子序列使其和最大的话,方法是多种的,但是存在O(n)的高效算法,那就是使用尺取法的思想不断地更新连续和的最大值。
具体实现的过程是在当前的和sum大于0,那么不断地推进区间右端点,如果小于0了,证明前面的部分的最大连续子序列和已经求出来了,直接将左端点推进至当前的位置。(这个是连续最大子序列和的计算)
回到题目,我们可以枚举断点,求出每个点左右两段的连续子序列和的最大值相加并取最大值即可。那么如何求解左右两段子序列的最大值呢?很明显的dp,令dpl[i]为1到i的区间内连续子序列和的最大值,同样地,令dpr[i]为i到n的区间内连续子序列和的最大值,那么答案就是max(dpl[i]+dpr[i+1]),根据最初的分析,一次遍历的过程就可以预处理出所有的dpl[i],反着遍历一次就可以求解dpr[i]。
整个实现的过程复杂度为O(n),如果要进一步提高效率,可以从输入下手,用scanf 代替cin,实际上cin也能过,并且在求前向连续和的时候可以在输入的时候求解。
本题的亮点是两个分段求连续的子序列和,一个正序的连续的子序列和,另一个逆序的连续的子序列和,然后因为是不相交的特点,一次遍历即可。
注意在设置最小(大)值的时候尽量INT_MIN, INT_MAX(求极值问题的时候)
不要简单的去设置一个0 或者一个大的数
还要注意要引入头文件#include<limits.h>
#include<iostream>
#include<cstring>
#include <stdio.h>
#include<limits.h>
#include<memory.h>
using namespace std;
int a[50010];
int dpl[50010],dpr[50010];
int T,n;
int main(){
//freopen("2.txt","r",stdin);
cin >> T;
while(T--){
memset(a,0,sizeof(a));
memset(dpl,0,sizeof(dpl));
memset(dpr,0,sizeof(dpr));
cin >> n;
int maxS=INT_MIN,curS=0;
for(int i = 0; i< n;i++){
cin >> a[i] ;
curS += a[i];
if(curS > maxS){
maxS = curS;
}
if(curS <0){
curS= 0;
}
dpl[i] = maxS;
}
maxS=INT_MIN; curS=0;
for(int i = n-1 ; i >=0; i--){
curS += a[i];
if(curS > maxS){
maxS = curS;
}
if(curS <0){
curS= 0;
}
dpr[i] = maxS;
}
int ans = INT_MIN;
for(int i =0; i< n-1;i++){
ans = max(dpl[i]+dpr[i+1],ans);
}
cout <<ans<<endl;
}
return 0;
}