D. Maximum Sum on Even Positions

某个tx面经上看到的题目,自己看了下觉得不会做,记录一下。

题目解析来自:D. Maximum Sum on Even Positions(思维,最大连续和,类dp)_jziwjxjd的博客-CSDN博客
以及:Codeforces 1373D - Maximum Sum on Even Positions (最大子段和)-布布扣-bubuko.com

说实话我读了半天才弄明白题目是什么意思。。

有一串序列,比如:

0 1 2 3 4 5 6 7 8 9 这样,那么它的所有偶数(下标)位置的元素和就是:
0 + 2 + 4 + 6 + 8 = 20

现在我们有机会旋转一次子序列(当然也可以不进行旋转,或者旋转某一长度的连续子序列),比如将子序列 0 1进行旋转,那么旋转后的序列就是:

1 0 2 3 4 5 6 7 8 9,那么现在的偶数下标元素和就是:
1 + 2 + 4 + 6 + 8 = 21

所以现在问题就是我们在进行一次旋转操作后,能够取得的偶数下标位置最大元素和是多少。

可以先考虑一下简单的情况:

  • 旋转的序列长度为1,那不还是没旋转嘛,所以和值不变
  • 如果旋转的序列长度为奇数,比如将序列 1 2 3 4 5 进行旋转,得到的序列就是:
    0 5 4 3 2 1 6 7 8 9,偶数下标和:
    0 + 4 + 2 + 6 + 8 = 0 + 2 + 4 + 6 + 8 = 20,会发现并没有区别。其实简单推一下可以发现:
    如果旋转的序列长度为奇数的话,其实是不会影响结果的

所以我们就只需要考虑旋转序列长度为偶数的情况就可以了,假设现在旋转序列 1 2 3 4,旋转后的序列就是:
0 4 3 2 1 5 6 7 8 9,偶数下标位置的序列和就是:
0 + 3 + 1 + 6 + 8 = 0 + 1 + 3 + 6 + 8 = 18,和值机会发生变化了。

那么现在就来关注这个变化,首先明确一个点,我们计算的是所有偶数下标位置的和,所以会发现序列:
0 4 3 2 1 5 6 7 8 9,和序列
0 2 1 4 3 5 6 7 8 9,得到的结果都是一样的,其实就是相当于把这个旋转的子序列里面的元素奇偶位置进行交换,而交换的顺序并不会影响最终的和值。比如上面这个例子就相当于把 2 和 1 交换,4 和 3 交换,那么得到的和值就是:原本的和值 20 + (1 - 2)+ (3 - 4) = 18。

说到这儿,其实思路就比较明确了,我们选择交换某一段偶数序列,交换后的和值的变化,其实就是 相邻位置的两个数交换产生的差值 的 累加。

借用上面参考链接的图:

因为只涉及到奇偶交换,位置的奇偶性是固定的

所以可以直接看作将某一偶数长度段中,第一个元素与第二个元素互换,第三个与第四个互换,以此类推……

如下图所示:

在这里插入图片描述
0 1 2 3 4 5 6 7 8 9,旋转2~8,变为
0 8 7 6 5 4 3 2 1 9,计算出来的偶数位置和值和
0 2 1 4 3 6 5 8 7 9,是一样的。

如果要替换原位置为 2 4 6 8 的元素,则只存在两种方案,将序列 1-8 旋转,或者将序列 2-9 旋转:

在这里插入图片描述
也就是说可以将每一个偶数位置的元素都与它的前面一个元素进行交换或者后面一种元素进行交换。

#include <bits/stdc++.h>

using namespace std;

const int maxn=2e5+10;
int n, a[maxn];
int main(){
	cin >> n;//数组元素的个数
	int ans=0, sum1=0, sum2=0, maxx=0;
	for(int i = 0; i < n; i++){
		cin >> a[i];
		if(i % 2 == 0)	ans+=a[i];//先计算出偶数位置的和值
	}

	for(int i = 1; i < n; i += 2){//偶数下标和后面一个位置交换
        //连续最大子序和的思路,如果某一段连续的和值已经小于0
        //那就可以舍弃这一段序列了
		sum1 = max(0, a[i] - a[i-1] + sum1);
		maxx = max(maxx,sum1);
	}
    for(int i = 2; i < n; i += 2){//偶数下标和前面一个位置交换
        sum2 = max(0, a[i] - a[i-1] + sum2);
        maxx = max(sum2, maxx);
    }
	ans += maxx;
	cout<<ans<<endl;
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
switch (Form) { case 1: p1 = CPoint(PositionS.x, PositionS.y); p2 = CPoint(PositionS.x + 48, PositionS.y); p3 = CPoint(PositionS.x + 61, PositionS.y); p4 = CPoint(PositionS.x + 100, PositionS.y); //p5 = CPoint(PositionS.x + 53, PositionS.y + 15); //p6 = CPoint(PositionS.x + 68, PositionS.y + 41); if (Status == 0) { p7 = CPoint(PositionS.x + 40, PositionS.y); p8 = CPoint(PositionS.x + 60, PositionS.y); } else if (Status == 1) { p7 = CPoint(PositionS.x + 49, PositionS.y + 5); p8 = CPoint(PositionS.x + 58, PositionS.y + 21); } break; case 2: p1 = CPoint(PositionS.x + 100, PositionS.y); p2 = CPoint(PositionS.x + 52, PositionS.y); p3 = CPoint(PositionS.x + 39, PositionS.y); p4 = CPoint(PositionS.x, PositionS.y); //p5 = CPoint(PositionS.x + 47, PositionS.y + 15); //p6 = CPoint(PositionS.x + 32, PositionS.y + 41); if (Status == 0) { p7 = CPoint(PositionS.x + 40, PositionS.y); p8 = CPoint(PositionS.x + 60, PositionS.y); } else if (Status == 1) { p7 = CPoint(PositionS.x + 51, PositionS.y + 5); p8 = CPoint(PositionS.x + 42, PositionS.y + 21); } break; case 3://11道岔 p1 = CPoint(PositionS.x, PositionS.y); p2 = CPoint(PositionS.x + 48, PositionS.y); p3 = CPoint(PositionS.x + 61, PositionS.y); p4 = CPoint(PositionS.x + 100, PositionS.y); p5 = CPoint(PositionS.x + 53, PositionS.y - 15); p6 = CPoint(PositionS.x + 68, PositionS.y - 41); if (Status == 0) { p7 = CPoint(PositionS.x + 40, PositionS.y); p8 = CPoint(PositionS.x + 60, PositionS.y); } else if (Status == 1) { p7 = CPoint(PositionS.x + 49, PositionS.y - 5); p8 = CPoint(PositionS.x + 58, PositionS.y - 21); } break; case 4://12道岔 p1 = CPoint(PositionS.x + 100, PositionS.y); p2 = CPoint(PositionS.x + 52, PositionS.y); p3 = CPoint(PositionS.x + 39, PositionS.y); p4 = CPoint(PositionS.x, PositionS.y); p5 = CPoint(PositionS.x + 47, PositionS.y - 15); p6 = CPoint(PositionS.x + 32, PositionS.y - 41); if (Status == 0) { p7 = CPoint(PositionS.x + 40, PositionS.y); p8 = CPoint(PositionS.x + 60, PositionS.y); } else if (Status == 1) { p7 = CPoint(PositionS.x + 51, PositionS.y - 5); p8 = CPoint(PositionS.x + 42, PositionS.y - 21); } break; }
最新发布
06-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值