P4552 [Poetize6] IncDec Sequence

题目描述

给定一个长度为 nn 的数列 {a_1,a_2,\cdots,a_n}a1​,a2​,⋯,an​,每次可以选择一个区间[l,r][l,r],使这个区间内的数都加 11 或者都减 11。

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

输入格式

第一行一个正整数 nn
接下来 nn 行,每行一个整数,第 i+1i+1行的整数表示 a_iai​。

输出格式

第一行输出最少操作次数
第二行输出最终能得到多少种结果

输入输出样例

输入 #1复制

4
1
1
2
2

输出 #1复制

1
2

说明/提示

对于 100\%100% 的数据,n\le 100000, 0 \le a_i \le 2^{31}n≤100000,0≤ai​≤231。

 

差分介绍: s[i]=a[i]-a[i-1]  (s差分数组,a原数组)

定义:

1.差分数组的前缀和就是原数组。sum[i]=a[i]=s[i]+sum[i-1];

  前缀和数组的差分就是原数组。

2. 【l,r】区间都加上x  只需改变   s[l]:+x   s[r+1]:-x

 

思路:

1.要使所有:数相同-->其数组的从2到n的差分数组都为0.

  如最后全为 1 1 1 1 

b[1]=1 ,b[2]=1-1=0, b[3]=1-1=0....

2.得到的差分数组的值为正数或负数(0不需要花费代价了)那么将正数-1同时负数+1作为一步时,代价是最小的。

如 [l,r]+1 ---->b[l]+1 ,b[r+1]-1   此时b[l]<0, b[r+1]>0

     [l,r] -1 ----->b[l]-1  b[r+1]+1  此时b[l]>0 b[r+1]<0

所以 差分的正负顺序没关系的。

设zh为2-n差分数组的正数之和,fh为负差分的绝对值之和。

则正负相抵消需要 min(zh,fh)步

3. 正负抵消完,还有以下两种情况

   (1)全是负数

    (2)全是正数

   这两种情况都是这个数一步一步加或者一步一步减,需要代价为abs(zh-fh)

综合2,3得到总代价为min(zh,fh)+abs(zh-fh)=max(zh,fh),第一个问题完成。

4.第二问,在已经把2-n的差分数组全为0了,还有b[1]没有考虑。

b[1]也有以下两种情况

   (1)b[1]独善其身,跟2-n的没关系,还是原来的b[1],一种方案。

    (2)b[1]在2-n正负抵消完后,跟剩下的全是正数、或者全是负数进行配对。

             若b[i](还剩下的数)<0,那么b[i]+1,b[1]-1

            若b[i]>0,那么b[i]-1,b[1]+1

          有abs(zh-fh)种方案

综合上述,一共有abs(zh-fh)+1种方案。

 

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
int a[100005],b[100005];
ll zh,fh;
int main()
{
    int n;
    cin>>n;
    for(int i=1; i<=n; i++){
       cin>>a[i];
    }
    b[1]=a[1];
    for(int i=2; i<=n; i++){
       b[i]=a[i]-a[i-1];
       if(b[i]>0) zh+=b[i];//zh 正差分绝对值之和
       else fh+=-b[i];//fh 负差分绝对值之和
    }
    cout<<max(zh,fh)<<endl<<abs(zh-fh)+1<<endl;
    return 0;
}

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值