- 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. - Source
- POJ Contest,Author:Mathematica@ZSU
- 题意:给定T个序列,对于每个序列,从中找出两个不重叠的子序列,使得加和起来最大。
- 思路:
- 维护两个数组lsum[],rsum[],lsum[i]表示i及i以前的最长连续序列和(一定包含i),rsum[j]表示j及j以后的最长连续序列和(一定包含j),则答案非常容易推出:ANS=max(ANS,lsum[i]+rsum[j] | 1<=i<=N,i+1<=j<=N),这样就可以两重循环,枚举i和j。
- 但是由于N(即序列长度)非常大,达到50000,所以任何N^2的算法都会超时,因此这题就要O(n)去解决,所以要对lsum和rsum进行改造,现在令lsum[i]表示i及i以前的最长连续序列和(不一定包含i),rsum[j]表示j及j以后的最长连续序列和(不一定包含j),则答案为ANS=max(ANS,lsum[i]+rsum[i+1] | 1<=i<=N)。这时求出lsum[],rsum[],就比较麻烦了,以lsum[i]为例,首先用f[i]来计算一定包含i的lsum,则真正的lsum[]就是max(f[i],lsum[i-1]),代码如下:
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int inf=-1e9;
4 int T,N;
5 int a[50005];
6 int lsum[50005];
7 int rsum[500005];
8 int f[50005];
9 int ANS=inf;
10 int main(){
11 scanf("%d",&T);
12 for(int z=1;z<=T;z++){
13 ANS=inf;
14 memset(a,0,sizeof(a));
15 memset(lsum,0,sizeof(lsum));
16 memset(rsum,0,sizeof(rsum));
17 memset(f,0,sizeof(f));
18 scanf("%d",&N);
19 for(int i=1;i<=N;i++) scanf("%d",&a[i]);
20 f[0]=inf; lsum[0]=inf;
21 f[N+1]=inf; rsum[N+1]=inf;
22 for(int i=1;i<=N;i++){
23 f[i]=max(a[i],f[i-1]+a[i]);
24 lsum[i]=max(f[i],lsum[i-1]);
25 }
26 memset(f,0,sizeof(f));
27 for(int i=N;i>=1;i--){
28 f[i]=max(a[i],f[i+1]+a[i]);
29 rsum[i]=max(f[i],rsum[i+1]);
30 }
31 for(int i=1;i<=N;i++){
32 ANS=max(ANS,lsum[i]+rsum[i+1]);
33 }
34 cout<<ANS<<endl;
35 }
36 return 0;
37 }