Educational Codeforces Round 90 (Rated for Div. 2)D.Maximum Sum on Even Positions

Educational Codeforces Round 90 (Rated for Div. 2)D.Maximum Sum on Even Positions 传送门

题意:在原有基础的数组上,可以反转一次数组,使得偶数上的和最大。

题解:注意到只可以翻转一次,故可以理解成求最大子序列翻转后最大。
可以注意到,如果开始端点是偶数且翻转长度也为偶数或开始端点是奇数且翻转长度也为奇数时,翻转一次是无意义的;故翻转只能考虑开始端点和结束端点奇偶不同时。
预处理奇数位-相邻偶数位(贡献≥0),前缀和求出最大连续子序列和,
ans=最大连续子序列和+奇数位和

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      	ll n,ans=0,sum=0;cin>>n;
      	vector<ll>a(n+5,0),x(n+5,0),y(n+5,0),f(n+5,0),q(n+5,0);
      	for(ll i=1;i<=n;i++)
      	{
      		cin>>a[i];
      		if(i&1)sum+=a[i];
		}
      	for(ll i=2;i<=n;i+=2)
      	{
      		x[i]=a[i]-a[i-1];
			y[i]=a[i]-a[i+1];  	
		}
		for(ll i=2;i<=n;i+=2)
		{
			f[i]=max(0ll,f[i-2]+x[i]);
			q[i]=max(0ll,q[i-2]+y[i]);
		}
		for(ll i=2;i<=n;i+=2)
		ans=max(ans,f[i]);
		for(ll i=2;i<=n-1;i+=2)
		ans=max(ans,q[i]);
		cout<<ans+sum<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hrd535523596/article/details/106968866