![[Luogu 2642] 双子序列最大和 [Luogu 2642] 双子序列最大和](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
Description
给定一个长度为n的整数序列,要求从中选出两个连续子序列,使得这两个连续子序列的序列和之和最大,最终只需输出最大和。一个连续子序列的和为该子序列中所有数之和。每个连续子序列的最小长度为1,并且两个连续子序列之间至少间隔一个数。
Input
第一行是一个整数表示n。
第二行是n个整数表示整数序列。
Output
一个数,两个连续子序列的序列和之和。
Range
对于30%的数据N<=100。
对于60%的数据有N<=10000。
对于100%的数据有N<=1000000。
数据保证运算过程不会超过long long(int64)。
Solution
可以想到维护两个数组 a[i],b[i] 分别存包括 i 向左的最大子段和与包括 i 向右的最大子段和。
但是我们如何求解答案呢?单单枚举两个数组是 O(n2)的复杂度。
有一种巧妙的方法,求完两个数组之后再遍历一遍,令 a[i] 表示 i 及 i 之前的最大子段和,b[i] 表示 i 及 i 之后的最大子段和。O(n)枚举断点即可
Code
#include<cstdio> #include<iostream> #define int long long using namespace std; int n; ]; ],b[]; signed main(){ scanf("%lld",&n); ;i<=n;i++) scanf("%lld",&val[i]); ;i<=n;i++) a[i]=max(val[i],a[i-]+val[i]); ]+val[i]); ;i<=n;i++) a[i]=max(a[i],a[i-]); ;i;i--) b[i]=max(b[i],b[i+]); int maxn=-0x3f3f3f3f; ;i<n;i++) maxn=max(maxn,a[i-]+b[i+]); printf("%lld",maxn); ; }