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 }