增减序列(差分)

分析:要想把整个数组变为同一个数,我们可以根据差分的思想来做。

差分定义:b[1]=a[1]

                  b[2]=a[2]-a[1]

                  ......

                  b[i]=a[i]-a[i-1]

由定义可知,可以把b[2]~b[n]全部变为0,那么整个数组就一样了。现在问题转换为如何用最少的操作次数把b[2]~b[n]全部变为0;由于差分数组操作是   b[ l ]+=1,b[ r+1 ]-=1/b[ l ]-=1,b[ r+1 ]+=1(操作的意思为在原数组a的区间[ l , r ] 加上1或减1)

那么对于2`~ n有四种操作(下边四种操作,l 和 r 都出现在了 1~ n中):

1. 2<=l , r <= n-1            (l,r都可以改变数组b  2~n 的值)b[l]+=1,b[r+1]-=1  /b[ l ]-=1,b[ r+1 ]+=1

2. l=1  ,2 <= r <= n-1         (只有r可以改变b数组 2~n的值) b[1]+=1,b[r+1]-=1  /b[ 1 ]-=1,b[ r+1 ]+=1

3. 2<= l <=n-1 ,r=n           (只有 l 可以改变b数组 2~n的值,注意:虽然r=n,但是我们改变的是b[r+1]                                            的值)                                         b[l]+=1,b[ r+1]-=1  /b[ l ]-=1,b[ r+1 ]+=1

4. l=1 , r=n                      执行b[l]+=1,b[r+1]-=1  /b[ l ]-=1,b[ r+1 ]+=1,相当于在原数组上整体加1                                           或减1,无意义 

我们的目的是把b数组的2~n的值变为0 ,且操作次数最少,那么我们优先使用操作1,执行完操作1后,b数组就只剩相同符号的数 了,然后再交替执行步骤 2和3(也可以只使用一个步骤,因为同一个步骤既可以加,也可以减,只是改变的值(b[1] 或 b[n+1])不一样) 就可以使b数组的2~n全部变为0

 操作1为什么可以使b数组全部变为相同的数呢 ?因为可以任选两个数执行(加1和减1  ,也可以是减1和加1),最终留下的数,就是正数(正数之和大于负数)或者负数(负数的绝对值之和大于正数)(操作1的次数等于==== min(正数,abs(负数))

当全部变为正数或者负数时,那么就可以执行步骤2或3,即b数组的2~n中不为0的数,加或减,最后变为0 ,那么操作2和3的步骤次数为 (假如正数比负数大  , 那么就等于==正数-abs(负数),负数比正数大的话,同理;

求出在保证最少次数的前提下,最终得到的数列可能有多少种?

前面说了最终全部的数都会和b[1]相等,  

  那么最终的b[1]被操作几次,b[1]就可以有几种情况。即 上边操作2,3的次数 再+1,加1是因为b[1]原本还有一个数(可以只执行操作3),

最后一个知识点:假如有两个数 a>b  那么  max(a,b) = min(a,b) + (a-b)

代码
 

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 1e5 + 10;
typedef long long LL;
int a[N],b[N];
int n;

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        b[i]=a[i]-a[i-1];
    }
    
    LL p=0,q=0;
    for(int i=2;i<=n;i++)
    {
        if(b[i]>0) p+=b[i];
        else q-=b[i];
    }
    
    cout<<max(p,q)<<endl<<abs(q-p)+1<<endl;
    
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值