[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;
}

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wym_king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值