CodeForces 1373 - D. Maximum Sum on Even Positions - 分类求最大连续子段和 ,思维

博客详细分析了CodeForces的D. Maximum Sum on Even Positions问题,重点在于理解如何通过翻转偶数长度子数组来最大化偶数下标元素之和。通过将问题转化为寻找两个方向的最大连续子段和,使用动态规划求解,最终得出答案。
摘要由CSDN通过智能技术生成

题目传送门:D. Maximum Sum on Even Positions

题目大意

给定一个数组,至多翻转一个子数组,使得偶数下标元素之和ans最大,输出ans(注意题目的数组下标从0开始)

思路

很显然我们要翻转偶数长度的子数组(因为奇数长度数组两端下标奇偶性相同,数组奇偶性呈中心对称,翻转之后奇数下标仍为奇数下标,偶数下标仍为偶数下标,那么翻转是无意义的),翻转之后奇偶下标互换

我们希望偶数下标元素之和最大,那么我们就要使翻转的数组中sum_奇 - sum_偶最大(因为翻转的数组下标奇偶性互换),想一想这不就是最大连续子段和吗?

但是需要注意的是我们要分别针对奇数下标开始的偶数下标开始的子数组求最大子段和(因为长度为偶数)

那么最后答案就是ans = 原数组sum_偶 + 子数组max(sum_奇 - sum_偶)

代码

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
ll qpow(ll base, ll n){ll ans = 1; while (n){if (n & 1) ans = ans * base % mod; base = base * base % mod; n >>= 1;} return ans;}
ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
ll a[N];
int main()
{
	int t;
	cin >> t;
	while (t --){
		int n;
		cin >> n;
		ll ans = 0, sum[2] = {0, 0}, maxsum = 0;
		for (int i = 1; i <= n; ++ i){
			scanf("%lld", &a[i]);
			if (i & 1) ans += a[i], a[i] = -a[i];//我是从1开始存的,所以变奇数
			//计算原数组偶数下标和,偶数下标元素值置为原来的相反数方便后面计算
		}
		for (int i = 0; i <= 1; ++ i){//偏移量,分为奇数下标开始和偶数下标开始
			for (int j = i + 1; j < n; j += 2){//i + 1是因为我的数组是从1开始存的
				sum[i] = max(0ll, sum[i] + a[j] + a[j + 1]);
				maxsum = max(sum[i], maxsum);
				//最大子段和,和小于0的段在取max时舍弃
			}
		}
		printf("%lld\n", ans + maxsum);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值