CH0304 IncDec Sequence(Inc序列)

16 篇文章 0 订阅
题目描述
给定一个长度为n的数列a1,a2,……,an,每次可以选择一个区间[l,r],使这个区间内的数都加1或者都减1。

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

输入输出格式
输入格式:
第一行一个正整数n
接下来n行,每行一个整数,第i+1行的整数表示ai

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

输入输出样例
输入样例#1: 
4
1
1
2
2
输出样例#1: 
1
2
说明
对于100%的数据,n≤100000,0≤ai≤2147483648。

写的好乱,看例子好理解点

求差分:相邻两项做差

数组 a r r [ 1 ] , a r r [ 2 ] … a r r [ n ] ​ arr[1],arr[2]…arr[n]​ arr[1],arr[2]arr[n]

差分 n u m [ 1 ] = a r r [ 1 ] , n u m [ i ] = a r r [ i ] − a r r [ i − 1 ] num[1]=arr[1],num[i]=arr[i]-arr[i-1] num[1]=arr[1],num[i]=arr[i]arr[i1]

a r r [ i ] = n u m [ 1 ] + n u m [ 2 ] + … + n u m [ i ] arr[i]=num[1]+num[2]+…+num[i] arr[i]=num[1]+num[2]++num[i]

数组值为差分前缀和


本题要求数列所有的数一样,也就要求是差分数组在 [ 2 , n ] [2,n] [2,n] 都为0

以下所有对差分的操作都在 [ 2 , n ] [2,n] [2,n]

如果对数组 [ i , j ] [i,j] [i,j] 范围内加减同一数字 k k k,可以转化为对差分数组的改变 n u m [ i ] + = k , n u m [ j + 1 ] − = k num[i]+=k,num[j+1]-=k num[i]+=k,num[j+1]=k (对范围的改变转化为对端点的改变)

(1)当 ± k ​ \pm k​ ±k成对出现时表示在区间内 ± k ​ \pm k​ ±k

(2)当 ± k \pm k ±k单独出现时表示在自身即后面所有元素内 ± k \pm k ±k (其实是操作区间[i,n])

也就是 n u m [ i ] = k ​ num[i]=k​ num[i]=k代表 i ​ i​ i后所有的数与前面所有数相差k


对于数据

i123456
数组112213
差分1010-12

差分数组中有一对 ± 1 \pm1 ±1 还有一个单独的2

先把 ± 1 \pm1 ±1 消除掉,也就是在区间 [ 3 , 4 ] [3,4] [3,4] 内减1, n u m [ 3 ] − = 1 , n u m [ 5 ] + = 1 num[3]-=1,num[5]+=1 num[3]=1,num[5]+=1

i123456
数组111113
差分100002

对于2的操作有三种

1 : a r r [ 1 , 5 ] 1:arr[1,5] 1:arr[1,5] 加一 , n u m [ 1 ] + = 1 , n u m [ 6 ] − = 1 ,num[1]+=1,num[6]-=1 num[1]+=1,num[6]=1 ,操作两次,对应 ( 1 ) ​ (1)​ (1)

i123456
数组333333
差分300000

2 : a r r [ 6 ] ​ 2:arr[6]​ 2:arr[6] 自己减一 , n u m [ 6 ] − = 1 ​ ,num[6]-=1​ num[6]=1 ,操作两次,对应 ( 2 ) ​ (2)​ (2)

i123456
数组111111
差分100000

3 : a r r [ 1 , 5 ] ​ 3:arr[1,5]​ 3:arr[1,5] 加一 , n u m [ 1 ] + = 1 , n u m [ 6 ] − = 1 ​ ,num[1]+=1,num[6]-=1​ num[1]+=1,num[6]=1 ,然后 a r r [ 6 ] ​ arr[6]​ arr[6] 自己减一

i123456
数组222222
差分200000

设差分数组中正数和ans1,负数和ans2

在将除 n u m [ 1 ] num[1] num[1] 外全部变为0的过程中,先把成对的 ± 1 \pm 1 ±1 消除,操作数为 m i n ( a n s 1 , a n s 2 ) min(ans1,ans2) min(ans1,ans2) 然后消除单独的正负数,操作数为 a b s ( a n s 1 − a n s 2 ) abs(ans1-ans2) abs(ans1ans2) ,总的操作数就是 m a x ( a n s 1 , a n s 2 ) max(ans1,ans2) max(ans1,ans2)

最后答案的种类就是 n u m [ 1 ] num[1] num[1] 的所有可能取值,从例子中看出就是单独的正负数的个数加1,因为 n u m [ 1 ] num[1] num[1] 的操作可以是(假如剩下的是正数,值为k) + 0 , + 1 , + 2 , . . . , + k +0,+1,+2,...,+k +0,+1,+2,...,+k 一共 k + 1 k+1 k+1

#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
static const auto io_sync_off = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}();

using ll=long long;
const int maxn=100005;
ll arr[maxn],nums[maxn];

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;++i)
        cin>>arr[i];
    for(int i=n-1;i>0;--i)
        arr[i]=arr[i]-arr[i-1];//差分
    
    ll ans1=0,ans2=0;
    for(int i=1;i<n;++i)
        if(arr[i]>0)
            ans1+=arr[i];
        else
            ans2+=abs(arr[i]);

    cout<<max(ans1,ans2)<<endl;
    cout<<abs(ans1-ans2)+1;
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值