P2642 双子序列最大和
首先考虑单个的最大子序列和
f[i] = max(f[i - 1] + a,a);
ans = max(ans,f[i]);
这里的预处理方法类似合唱队列我们处理pre和nex两个数组,分别表示以i为结尾1~i
的最大子序列和,以及以i为起点的i~n
的最大子序列和,我们枚举中间点,答案就是
ll ans = pre[1] + nex[3];
for(int i = 3; i < n; ++ i){//题目要求至少隔一个数
ans = max(ans, pre[i - 1] + nex[i + 1]);
}
注意我们要先给ans赋值为 pre[1] + nex[3]
,不能写成0,因为我们这里for循环的时候不能取到n,因为n+1,但是如果n == 3,那么我们这里for循环是不会进去的,会直接跳出,ans这时候就会变成0而不是正确答案pre[1] + nex[3]
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<cmath>
#include<cstring>
using namespace std;
//typedef unsigned long long ll;
typedef long long ll;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 1000007, M = 5000007;
const ll INF = 1e14;
inline void read(int &x)
{
char c = getchar();
while ((c < 48) || (c > 57)) c = getchar();
x = c ^ 48;c = getchar();
while ((c >= 48) && (c <= 57))
{
x = x * 10 + (c ^ 48);
c = getchar();
}
}
int n, m;
int t;
ll tot, cnt, ans;
int arr[N];
ll a[N];
ll pre[N], nex[N];
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%lld", &a[i]);
}
pre[1] = a[1];
for(int i = 2; i <= n; ++ i)
pre[i] = max(pre[i - 1] + a[i], a[i]);
for(int i = 2; i <= n; ++ i)
pre[i] = max(pre[i - 1], pre[i]);
nex[n] = a[n];
for(int i = n - 1; i >= 1; -- i)
nex[i] = max(nex[i + 1] + a[i], a[i]);
for(int i = n - 1; i >= 1; -- i)
nex[i] = max(nex[i + 1], nex[i]);
ll ans = pre[1] + nex[3];
for(int i = 3; i < n; ++ i){//题目要求至少隔一个数
ans = max(ans, pre[i - 1] + nex[i + 1]);
}
printf("%lld\n" ,ans);
return 0;
}