题目描述:
N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的。当所给的整数均为负数时和为0。
例如:{-2,11,-4,13,-5,-2, 4}将 -4 和 4 交换,{-2,11,4,13,-5,-2, -4},最大子段和为11 + 4 + 13 = 28。
输入
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N + 1行:N个整数(-10^9 <= A[i] <= 10^9)
输出
输出交换一次后的最大子段和。
输入样例
7
-2
11
-4
13
-5
-2
4
输出样例
28
分析:关于V1的一个变形,只要开数组保存一下前缀和、后缀和。一共两种情况,第一种是两个数字交换对最大值不产生影响,这种情况是直接和前一个长度的最大值有关,另一个就是对最大值产生影响,那么就是在正反求一次最大子段和即可(需要稍加变形)
那么具体代码如下:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
long long maxl[10000001];
long long maxr[1000001];
long long n;
long long a[1000011];
int main(){
scanf("%lld",&n);
long long ans=0;
for (long long i=1;i<=n;i++) scanf("%lld",&a[i]);
for (int i=1;i<=n;i++){
maxl[i]=maxl[i-1]+a[i];
if (maxl[i]<0) maxl[i]=0;
maxr[n-i+1]=maxr[n-i+2]+a[n-i+1];
if (maxr[n-i+1]<0) maxr[n-i+1]=0;
ans=max(ans,maxl[i]);
}
long long summ=0,maxx=a[1];
for (long long i=2;i<=n;i++){
summ=max(summ+a[i-1],maxx);
ans=max(ans,summ+maxr[i+1]);
maxx=max(maxx,a[i]);
}
summ=0,maxx=a[n];
for (long long i=n-1;i>0;i--){
summ=max(summ+a[i+1],maxx);
ans=max(ans,summ+maxl[i-1]);
maxx=max(maxx,a[i]);
}
cout<<ans;
return 0;
}