POJ 2479 Maximum sum && sicily 1090

来源:互联网 发布:大浦洞导弹 知乎 编辑:程序博客网 时间:2024/06/11 01:24

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

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)

Output

Print exactly one line for each test case. The line should contain the integer d(A).

Sample Input

1101 -1 2 2 3 -3 4 -4 5 -5

Sample Output

13

Solution

题意就是给出一个序列,求序列中最大的两段和,这两个连续子序列可以连续,就是一个连续子序列。

一开始看觉得是最长上升子序列的变形,后来有人说可以划分成两个子问题,就是求左边的最长上升子序列和右边的最长上升子序列的和,枚举划分点。

瞬间就有思路了~!另外右边的可以不求出具体的和,只需要求出右边序列中每一个元素的以该元素结尾的最大和即可。

dp_r[i]表示从右边开始,以第i个元素结尾的最大连续和

dp_l[i]表示从左边开始,以第i个元素结尾的最大连续和

get_l[i]表示左边序列到第i个元素的最大连续和

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;int dp_r[50005], dp_l[50005], get_l[50005], a[50005];int main(){  int t;  scanf("%d", &t);  while (t--)  {    int i, j, n, temp, ans;    scanf("%d", &n);    for (i = 1; i <= n; ++i)    {      scanf("%d", &a[i]);      dp_l[i] = max(dp_l[i-1]+a[i], a[i]);      if (i == 1) get_l[i] = dp_l[i]; //左边最长上升子序列的和      else get_l[i] = max(get_l[i-1], dp_l[i]);    }    dp_r[n+1] = 0;    for (i = n; i > 1; --i) //枚举划分点    {      dp_r[i] = max(dp_r[i+1]+a[i], a[i]);      if (i == n) ans = dp_r[i] + get_l[i-1];      else ans = max(ans, dp_r[i]+get_l[i-1]);    }    printf("%d\n", ans);  }  return 0;}

0 0