P2642 双子序列最大和
简单的普及题
题意:求两个不相接的子段,使之和最大
最简单的最大子段和可以$O(n)$求解
此题同样
令$f[i][0]$表示以$i$结尾的第一段子段和,$f[i][1]$表示以$i$结尾的总的和
有
$$f[i][0] = max(f[i-1][0],0)+a[i]$$
$$f[i][1] = max(max\left \{ f[j][0] \right \},f[i-1][1])\;(j<i-1)$$
可以维护前缀最大值
时间复杂度 $O(n)$
代码如下
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #define ll long long 6 using namespace std; 7 8 template <typename T> void in(T &x) { 9 x = 0; T f = 1; char ch = getchar(); 10 while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} 11 while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();} 12 x *= f; 13 } 14 15 template <typename T> void out(T x) { 16 if(x < 0) x = -x , putchar('-'); 17 if(x > 9) out(x/10); 18 putchar(x%10 + 48); 19 } 20 //------------------------------------------------------------- 21 22 const int N = 1e6+7; 23 int n; 24 ll a[N],f[N][2],ans = -1e15,maxn = -1e15; 25 26 int main() { 27 int i; in(n); 28 memset(f,~0x7f,sizeof(f)); 29 for(i = 1;i <= n; ++i) in(a[i]); 30 f[1][0] = a[1]; f[2][0] = max(f[1][0]+a[2],a[2]); 31 for(i = 3;i <= n; ++i) { 32 maxn = max(maxn,f[i-2][0]); 33 f[i][0] = max(f[i-1][0]+a[i],a[i]); 34 f[i][1] = max(maxn+a[i],f[i-1][1]+a[i]);//debug f[i][1] 不能直接等于a[i] 35 ans = max(ans,f[i][1]); 36 } 37 out(ans); 38 return 0; 39 }