欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[Poetize6] IncDec Sequence 差分

程序员文章站 2022-03-06 11:56:02
...

题目描述

给定一个长度为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;
}

 

 

 

 

 

 

 

 

 

 

相关标签: 差分