P2642 双子序列最大和

${\color{cyan}{>>Question}}$

简单的普及题

题意:求两个不相接的子段,使之和最大

最简单的最大子段和可以$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 }

 

posted @ 2019-08-26 19:48  陈星卿  阅读(239)  评论(0编辑  收藏  举报