基础知识:差分

差分

1、对于给定一个序列 A ,它的差分序列为:

B [ 1 ] = A [ 1 ] , B [ i ] = A [ i ] − A [ i − 1 ] ( 2 < = i < = n ) B[1] = A[1],B[i] = A[i] - A[i-1](2 <= i <= n) B[1]=A[1],B[i]=A[i]A[i1](2<=i<=n)

2、差分 和 前缀和 是一对逆运算:差分序列 B 的前缀和就是序列 A,前缀和 S 的差分序列也是序列A。

差分序列 B 的前缀和:

= B [ 1 ] + B [ 2 ] + B [ 3 ] + . . . + B [ i ] = B[1] + B[2] + B[3] + ... + B[i] =B[1]+B[2]+B[3]+...+B[i]

= A [ 1 ] + A [ 2 ] − A [ 1 ] + A [ 3 ] − A [ 2 ] + . . . + A [ i ] − A [ i − 1 ] =A[1] + A[2] - A[1] + A[3] - A[2] + ... + A[i] - A[i - 1] =A[1]+A[2]A[1]+A[3]A[2]+...+A[i]A[i1]

= A [ i ] = A[i] =A[i]

前缀和 S 的差分序列:

= S [ i ] − S [ i − 1 ] = S[i] - S[i-1] =S[i]S[i1]

= A [ 1 ] + A [ 2 ] + . . . + A [ i − 1 ] + A [ i ] − ( A [ 1 ] + A [ 2 ] + . . . + A [ i − 1 ] ) = A[1] + A[2] + ... + A[i-1] + A[i] - (A[1] + A[2] + ... + A[i-1]) =A[1]+A[2]+...+A[i1]+A[i](A[1]+A[2]+...+A[i1])

= A [ i ] = A[i] =A[i]

3、作用:把序列 A 的区间 [ l , r ] [l,r] [l,r] 加 d(即把 A l , A l + 1 , . . . , A r A_l,A_{l+1},...,A_r Al,Al+1,...,Ar 都加上 d),其差分序列 B 的变化为 B l B_l Bl 加 d, B r + 1 B_{r+1} Br+1 减 d,其他位置不变。

A 序列加d : A [ l ] + d , A [ l + 1 ] + d , . . . , A [ r ] + d A[l]+d,A[l+1] + d,...,A[r]+d A[l]+d,A[l+1]+d,...,A[r]+d

变化后差分序列:

B [ l ] = A [ l ] + d − A [ l − 1 ] = B [ l ] 原 + d B[l] = A[l] + d - A[l-1] = B[l]_{原} + d B[l]=A[l]+dA[l1]=B[l]+d

B [ l + 1 ] = A [ l + 1 ] + d − ( A [ l ] + d ) = B [ l + 1 ] 原 B[l+1] = A[l+1] + d - (A[l] + d) = B[l+1]_{原} B[l+1]=A[l+1]+d(A[l]+d)=B[l+1]

B [ r + 1 ] = A [ r + 1 ] − ( A [ r ] + d ) = B [ r + 1 ] 原 − d B[r+1] = A[r+1] - (A[r] + d) = B[r+1]_{原} - d B[r+1]=A[r+1](A[r]+d)=B[r+1]d

AcWing 100. IncDec序列

题目:

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

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

输入格式

第一行输入正整数 n。

接下来 n 行,每行输入一个整数,第 i+1 行的整数代表 ai。

输出格式

第一行输出最少操作次数。

第二行输出最终能得到多少种结果。

数据范围

0 < n ≤ 10^5
0 ≤ ai < 2147483648

输入样例:

4
1
1
2
2

输出样例:

1
2

思路:

题目对序列 A 的操作就是对 B 1 , B 2 , . . . , B n B_1,B_2,...,B_n B1,B2,...,Bn 任选2个数,一个加1,一个减1.

题目要求序列 A 的每一个数都要相同,可以转换为 差分序列 B 2 , B 3 , . . . , B n B_2,B_3,...,B_n B2,B3,...,Bn 全变为 0.

B 1 , B 2 , . . . , B n B_1,B_2,...,B_n B1,B2,...,Bn 任选2个数 有四种情况:

1、选 B i 和 B j , 2 < = i , j < = n B_i 和 B_j, 2 <= i,j <= n BiBj,2<=i,j<=n , 为尽量让序列为 0 ,应选择一正一负,相互抵消,逐渐趋近0.

2、选 B 1 , B j 其 中 2 < = j < = n B_1,B_j 其中 2 <= j <= n B1,Bj2<=j<=n

3、选 B i , B n + 1 其 中 2 < = i < = n B_i,B_{n+1} 其中 2 <= i <= n Bi,Bn+12<=i<=n

4、选 B 1 , B n + 1 B_1,B_{n+1} B1,Bn+1 相当于选取全部加减,没有意义。

设 差分序列 B 中正整数的和为 P,负整数的和为 Q,在正负数的选取下,先采用第一种选法,可选min(P, Q),还有|P-Q|种没有匹配,可以选择第二种或者第三种,总次数为 min(P, Q) + |P-Q| = max(P, Q);

根据|P - Q| 次第二或第三种选择,可以选择出 |P - Q| + 1 种 B 1 B_1 B1 ,所以 A 序列 有|P - Q| + 1 种。

算法:

import java.util.*;

public class Main{
    
    public static int MAX = 100010;
    public static int[] A = new int[MAX];
    public static int[] B = new int[MAX];
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        long poSum = 0, neSum = 0;
        for(int i = 0; i < n; i++) {
            A[i] = scanner.nextInt();
            if(i == 0) B[i] = A[i];
            else {
                B[i] = A[i] - A[i-1];
                if(B[i] > 0) poSum += B[i];
                else neSum -= B[i];
            }
        }
        System.out.println(Math.max(poSum, neSum));
        System.out.println(Math.abs(poSum - neSum) + 1);
    }
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值