IncDec序列

Inc和Dec是  increase ,decrease两个单词的缩写所以这个问题又叫增减序列。

这个问题是这样的:

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

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

思路:

        我们观察到,题目要求我们对一个区间中的数加一或者减一,很容易想到差分。

差分是什么呢?

        差分就是前缀和的逆运算,前缀和是原数组前 n 项的和,差分就是 差分序列的前n项和是原数组的第n项。

        假设a是原序列,b是差分序列。

        差分序列可以由原数组求得:b[i]=a[i]-a[i-1] 。

那我们怎么样对整个序列用差分来操作呢?

        假设我们对[l,r]这个区间的数都加上c,我们可以

        b[l]+=c,b[r+1]-=c

        用两个数的操作来改变整个序列的操作。

对于这道题:

题目要求原序列每个数都一样,可以转换为差分序列 b2 到 bn 都为0,需要最少多少步,

在最少的步数下b1有多少种情况。

由于差分序列对 l 和 r+1 两个数来操作,所以差分序列最大达到了n+1.由于要在差分序列的n个数里面挑两个进行操作,可以分为以下四种情况:

         1.对b2 到 bn 中选两个,一个+1,一个-1.

 

2.选定b1,然后在 b2 到 bn中选一个+1或者-1。

 

 3.选定bn+1,然后再b2到bn中选一个+1或者-1.

4.选中整个序列+1或者-1没有意义。

目标是将b2到bn所有的数都变为0.

我们假设差分序列 b2 到 bn 中所有正数的和为p,所有负数的和为q,

优先第一种操作,因为第一种操作可以同时改变两个数,当所有的正数或负数都变为0之后,我们在2和3中选择。

              最少操作步数为  min(p,q)+\left |p-q \right |

                                       第一种操作        第二,三种操作

在最少操作步数下,b1的种类与第二种操作的次数有关,当第一种操作结束之后,有  \left |p-q \right |种操作,分配给2和3,可知第二种操作可以有\left |p-q \right |+1

代码如下:

       

#include<iostream>
#include<cstring>
#include<cmath>

using namespace std;

const int  N=100010;

int a[N],b[N];

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

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值