[Poetize6] IncDec Sequence 差分

题目描述

给定一个长度为n的数列a1,a2,⋯,an a1​,a2​,⋯,an​,每次可以选择一个区间[l,r] ,使这个区间内的数都加1或者都减1。

请问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列有多少种。

 

题解:

dif 表示 a[i]与a[i-1]的差值,将a[1]定为基,则对这个差值组成的数组只要令2到n项都为0,求出最小操作次数以及最后基值a[1]有多少可能。

  对差值连续的两个数, 正数(X)和负数(Y),要通过N = min(X,abs(Y))让其中一方变为0.

    对一个正数(X)要通过N = abs(X)让其变为0.

    对一个负数(Y)要通过N = abs(Y)让其变为0.

   在这个过程,我们发现正数和负数可以抵消。例如对 2 5 1,dif是 3 -4,需要min(3,abs(-4))=3步让其中一个为0,对原数组操作就是5减三变成2.   这时原数组就是2,2,1,而此时dif 差值数组是 0,-1.  这-4抵消了3次变成-1,还要经过1次才行,我们发现abs(-4)-3 =1,于是多试几次得出结论对一个正数(X)和负数(Y)都变成0 需要经过 min(X,abs(Y))+abs(X-Y)==max(X,abs(Y))次.

这个结论从连续的两个数推广到整个差值数组,定义totz是所有正数的和,totf是所有负数的和比较两者最大值即为最小操作次数

那会有多少种可能呢?

从上面看出所有差值为正的和totz与所有差值为负的绝对值的和totf  两种中小者是抵消的次数,最后还剩下 abs(X-Y)次操作是改变整个数列值的操作。例如 totz = 6,totf = 5,5次是可以看作正负抵消,最后一次是确定整个数列的值。又例如上面例子2,5,1

3次抵消变成2,2,1最后一次操作让最后一个数加一是确定整个数列变成2.   也就是说多出的abs(X-Y)次操作可以管也可以不管前面的差分,所以答案就是abs(X-Y)+1

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[100005];
int main()
{
	int n,dif;
	ll totz=0,totf=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(i>=2){
		dif = a[i]-a[i-1];
		if(dif>0)totz+=dif;
		else totf-=dif;
		}
	}
	printf("%lld\n%lld",max(totz,totf),abs(totz-totf)+1);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41603898/article/details/89072743