0
点赞
收藏
分享

微信扫一扫

【蓝桥杯】一学就会的小技巧(二):差分

桑二小姐 2022-04-01 阅读 37

header

🍑前言:

🍹🍹差分跟前缀和类似,不过它主要用于区间修改,在对数组进行n次区间修改后,利用差分可以快速得到修改后的新数组。

题目传送门:🚀🚀🚀

题目链接
ACWing797.差分(模板题)https://www.acwing.com/problem/content/799/

🍓差分:

插图

👩🏻‍🏫在输入时引入一个新数组diff[]记录num[i]num[i - 1]的差:

0123456
num122121
diff0110-11-1

⭐通过diff[]数组可以求出num[]的每一项,num[i] = diff[1] + diff[2] + ... + diff[i]

☕经过第一次区间修改1 3 1

0123456
num233121
diff0210-21-1

☕对区间1~3的值全部加1,可以发现diff[]数组只有diff[1]diff[4]的值发生了改变,diff[1]+1diff[4]-1

☕经过第二次区间修改3 5 1

0123456
num234231
diff0211-21-2

☕经过第三次区间修改1 6 1

0123456
num345342
diff0311-21-2

⭐可以看到,对于每次区间修改l r cdiff[]只有两个位置会发生变化,那么我们只需要维护这两个位置就可以了,其中diff[l] = diff[l] + cdiff[r] = diff[r] - c

⭐最后如果要得到修改后的原数组,只需要一次遍历diff[],对其求前缀和即可,时间复杂度 O ( N ) O(N) O(N)

🍦Java代码:

import java.util.Scanner;

public class Main {

    public static int[] num = new int[10005];
    // 记录相邻两项差,数组要开的大一些,防止越界
    public static int[] diff = new int[10005];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            num[i] = sc.nextInt();
            diff[i] = num[i] - num[i - 1];
        }
        for (int i = 0; i < m; i++) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            int c = sc.nextInt();
            diff[l] += c;
            diff[r + 1] -= c; 
        }
        sc.close();
        // 利用diff[]得到原数组,差分数组求前缀和
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += diff[i];
            num[i] = sum;
            System.out.print(num[i] + " ");
        }
    }
}

举报

相关推荐

0 条评论