POJ2479:Maximum sum

来源:互联网 发布:淘宝白内障器械 编辑:程序博客网 时间:2024/06/05 04:02

总时间限制

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]1i的区间内连续子序列和的最大值,同样地,令dpr[i]in的区间内连续子序列和的最大值,那么答案就是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; }