1481:Maximum sum (前缀和+dp)

【题目描述】

    对一个序列A={a1, a2,..., an}给出函数:

                     t1     t2 
d(A) = max{ ∑ai + ∑aj | 1 <= s1 <= t1 < s2 <= t2 <= n }
i=s1 j=s2
求出该函数最大值。

【题目链接】

    http://noi.openjudge.cn/ch0206/1481/

【算法】

    类似股票买卖,决策一个i的位置,i之前的最大子段和和i+1及其之后的最大子段和的最大值。注意前i个最大子段和的求法:要记录一个前缀和最小值,注意初始化应当为a【1】和0的较小值(wa了半天才发现)。

【代码】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int t,n,i;
 4 int a[51000],pre[51000],post[51000];
 5 int main()
 6 {
 7     scanf("%d",&t);
 8     while(t--) {
 9         memset(pre,0,sizeof(pre));
10         memset(post,0,sizeof(post));
11         scanf("%d",&n);
12         for(i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=a[i-1];
13         pre[1]=a[1];
14         int minn=min(0,a[1]);
15         for(i=2;i<n;i++) minn=min(minn,a[i]),pre[i]=max(pre[i-1],a[i]-minn);
16         post[n]=a[n]-a[n-1];
17         int maxn=a[n];
18         for(i=n-1;i>1;i--) maxn=max(maxn,a[i]),post[i]=max(post[i+1],maxn-a[i-1]);
19         int ans=-1e9;
20         for(i=1;i<n;i++)
21             ans=max(ans,pre[i]+post[i+1]);
22         printf("%d\n",ans);
23     }
24     return 0;
25 }

 

    

posted @ 2018-08-01 00:59  飞飞翔滴少年  阅读(515)  评论(0编辑  收藏  举报