题目
给你一个有n个元素的数组A。
选择两个连续的 l r l < r 翻转数组
只能通过一次或者0次翻转,使得数组的偶数位和最大。
题解思路
如果数组进行了翻转,可能选择奇数开始偶数结束,或者相反,这样就可以让这一段的奇数偶数总和互换。
放到数组上,就是两种情况。从 i - 1 到 i 或者从 i 到 i + 1 。i为偶数。
我们做出差分数组。
求这个差分数组里的最大子段和不就是可以增加的最大值了吗。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200100;
int a[N] ;
int n ;
long long sum1[N] ;
long long sum2[N] ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while ( T-- )
{
int cnt1 = 0 , cnt2 = 0 ;
cin >> n ;
long long sum = 0 ;
for (int i = 0 ; i < n ; i++ )
{
cin >> a[i] ;
if ( i % 2 == 0 )
sum += a[i];
}
for (int i = 2 ; i < n ; i+= 2 )
{
sum1[cnt1] = a[i-1] - a[i] ;
cnt1++;
}
for (int i = 0 ; i + 1 < n ; i+= 2 )
{
sum2[cnt2] = a[i+1] - a[i] ;
cnt2++;
}
long long sp = 0 , sm = 0 ;
for (int i = 0 ; i < cnt1 ; i++ )
{
if ( sp > 0 )
sp += sum1[i] ;
else
sp = sum1[i] ;
if ( sp > sm )
sm = sp ;
}
long long sk = 0 ;
sp = 0 ;
for (int i = 0 ; i < cnt2 ; i++ )
{
if ( sp > 0 )
sp+= sum2[i] ;
else
sp = sum2[i] ;
if ( sp > sk )
sk = sp ;
}
cout << sum + max({sk,sm,(long long )0}) << "\n" ;
}
return 0 ;
}