codeforces 贪心 Slime

 题目简述:

        给定一个数组,相邻两个之间可以随便相减,减数保留,被减数消失,最后这个数组只剩下一个数,求最后这个数的最大可能值。

贪心:

        首先给定一系列数  x1,x2,x3,x4......xn。

        我们考虑最后一次相减,必定是 x1,x2...... xi 得到的结果与 xi+1 ....  xn 得到的结果,这两堆相减的结果,可以前者减去后者,也可以后者减去前者 ,但无论那种结果,所得的表达式中,一定有某个xk, 它的前面是 + , 也一定存在某个 xp, 它的前面是 - ,其他所有的数可以是 + ,也可以是 - ,但如果要结果最大,就要对这些数取绝对值。然后我们找到数组中一个最大的元素,它前面为 +, 找到一个数组中最小的元素,它的前面为 -,直接遍历即可。

        也就是说,+x1+x2+........+xn 这样的序列是不可能的,-x1-x2....-xn也是不存在的. 

        例如我们考虑两个数,有一个 + ,有一个 -。 

        考虑三个数的时候,我们先把两个数看成一个整体 1 个 +, 1个-,然后第三个数作用时,可能是2个+ 1个-,也可能是2个- 1个 +。

        然后我们用数学归纳法,假设 对 1,2,3......k 个数都成立,那么 k+1个数时,我们把这 k + 1个数 分为两堆,第一队 i 个,第二堆 j 个  (i 和 j 都大于1),第一堆可以产生(1,i-1),(2,i-2).....(i-1,1)对+-对(这里是根据数学归纳法),同理第二堆 (1,j-1),(2,j-2).....(j-1,1),这两堆自由组合就可以生成(1,k-1)......(k-1,1)对+-符号,(注意,(1,k-1)和(k-1,1)是有一堆为 1 时才产生的)。

        证毕。(有点不严谨,欢迎读者指正) 

 

   

AC Code:

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include <numeric>



int main() {
	int N = 0;
	cin >> N;
	vector<int> a(N, 0);
	int maxx = INT_MIN; int minn = INT_MAX;
	for (int i = 0; i < N; i++) {
		cin >> a[i];
		maxx = max(maxx, a[i]);
		minn = min(minn, a[i]);
	}
	// 至少一个 - ,至少一个 +
	// 最小的那个数 - ,最大的那个数 +, 其他全部取绝对值
	if (N == 1) {
		cout << a[0]; return 0;
	}
	long long ans = maxx - minn;
	int maxa = 0; int minb = 0;
	for (int i = 0; i < N; i++) {
		if (a[i] == maxx && maxa == 0) {
			maxa = 1;
			continue;
		}
		else if (a[i] == minn && minb == 0) {
			minb = 1;
			continue;
		}
		else {
			ans += abs(a[i]);
		}
	}
	cout << ans;
}

 

 

 

        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值