Maximum sum
题意
求一个序列的两个子段,使得两段子段的和最大
即找两段 (s1,t1) 和 (s2,t2),使得 \(\displaystyle \sum_{i=s1}^{t1}{a_i} + \displaystyle \sum_{i=s2}^{t2}{a_i}\) 最大
做法
分别从序列起点和末端进行 dp 分别找到最大的一段子段,然后枚举断点拼接即可
code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<math.h>
#define ll long long
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x*f;
}
const ll inf=1e9+10;
const ll maxn=5e4+10;
ll T,n,ans=-inf;
ll a[maxn],f[maxn],g[maxn],maxxl[maxn],maxxr[maxn];
int main(void)
{
scanf("%lld",&T);
while(T--)
{
ans=-inf;
memset(f,-0x3f,sizeof(f));
memset(g,-0x3f,sizeof(g));
memset(maxxl,-0x3f,sizeof(maxxl));
memset(maxxr,-0x3f,sizeof(maxxr));
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",a+i);
f[1]=a[1];
g[n]=a[n];
maxxl[1]=a[1];
maxxr[n]=a[n];
for(int i=2;i<=n;i++)
{
f[i]=std::max(f[i-1]+a[i],a[i]);
}
for(int i=n-1;i;i--)
{
g[i]=std::max(g[i+1]+a[i],a[i]);
}
for(int i=2;i<=n;i++)
{
maxxl[i]=std::max(maxxl[i-1],f[i]);
}
for(int i=n-1;i;i--)
{
maxxr[i]=std::max(maxxr[i+1],g[i]);
}
for(int i=2;i<=n;i++)
{
ans=std::max(ans,maxxl[i-1]+maxxr[i]);
}
printf("%lld\n",ans);
}
return 0;
}