AcWing 100. IncDec序列

题目链接:100. 增减序列 - AcWing题库

参考题解:AcWing 100. IncDec序列 - AcWing

    


思路

1.首先通过差分构造差分数组,要保证所有数都相同,就要确保差分数组从下标2到n的所有数组值等于0

2.通过贪心,选取差分数组中的两个数(事情上是选取了原数组一个范围大于1的区间,注意是区间,不是单独的数),一个+1,另一个-1,+1在前为曾1,-1在前为-1,

贪心理由:因为对一个区间做修改,最多对差分数组修改两个数(加1或者减1),确保每次操作都尽量修改两个数,就可以使修改次数最少

通过贪心修改差分数组的值后,此时数组有三种情况:

(1)全为0,结束

(2)还有数组值为正值

(3)还有数组值为负值

3.对于(2)(3)两种情况,只能单独增加1或者减去1,假设该差分数组值不为0的下标为k,事实上可以理解为两种特殊情况:(1)一个数字单独加1减1,相当于对数组添加一个元素,下标为n+1,对于区间[k,n+1]加1或者减1,而实际上n+1是不存在的,所以相当与只是单独对该元素加1或者减1,不影响结果;(2)对于第一个元素做修改(注意只要修改第一个元素,那么就会产生不同的解了),修改第一个元素对差分数组无影响,因为差分数组是从下标2开始的,那么就是区间[1,k]减1或者加1

4.(1)由2.3可以得出,一共需要操作的次数等于所有正数的和与负数的和的最大值。

(2)由3可以得出,对剩下的差分数组值求和取绝对值,该值就是可以修改第一个元素的所有次数(即在最小修改次数下不同解的个数),但要注意的是还有+1,因为当差分数组全为0时本身就有一组解,不要忽略掉。


AC代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
#define maxn 100007
#define ll long long

using namespace std;

ll a[maxn],f[maxn];
 
int main()
{
	ll sum1 = 0,sum2 = 0;
	int n;
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		cin >> a[i];
		f[i] = a[i] - a[i-1];
	}
	
//	for(int i=1;i<=n;i++)
//		cout << a[i] << " ";
//		
//	cout << endl << endl;
//	
//	for(int i=1;i<=n;i++)
//		cout << f[i] << " ";
//	cout << endl;	

	for(int i=2;i<=n;i++)
	{
		if(f[i] > 0)
			sum1+= f[i];
		if(f[i] < 0)
			sum2+= abs(f[i]);    //sum2-= f[i]更简洁
	}
	cout << max(sum1,sum2) << endl;	
	cout << abs(sum1-sum2) + 1 << endl;
	return 0;
} 
/*
任选两个数的方法可分为四类
1、2 <= i , j <=n(优先)
2、i = 1, 2 <=j <=n
3、2 <= i <= n , j = n + 1
4、i = 1, j = n + 1(没有意义)
*/
//4 4 4 3
//4 0 0 -1
//sum2 =1 
//ans1:4 0 0 0
//ans2:3 0 0 0
//
//4 4 4 2
//4 0 0 -2 
//sum2 = 3
//ans1:2 0 0 0
//ans2:4 0 0 0
//ans3:3 0 0 0
//	
//4 4 4 2 1
//4 0 0 -2 -1
//sum2 = 4
//ans1: 1 0 0 0 0
//ans2: 4 0 0 0 0
//ans3: 5 0 0 0 0
//  

posted @ 2022-05-05 08:42  光風霽月  阅读(18)  评论(0编辑  收藏  举报