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;
}
posted @ 2021-02-20 09:16  雾隐  阅读(52)  评论(0编辑  收藏  举报