🍑前言:
🍹🍹差分跟前缀和类似,不过它主要用于区间修改,在对数组进行n次区间修改后,利用差分可以快速得到修改后的新数组。
题目传送门:🚀🚀🚀
题目 | 链接 |
---|---|
ACWing797.差分(模板题) | https://www.acwing.com/problem/content/799/ |
🍓差分:
👩🏻🏫在输入时引入一个新数组diff[]
记录num[i]
与num[i - 1]
的差:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
num | 1 | 2 | 2 | 1 | 2 | 1 | |
diff | 0 | 1 | 1 | 0 | -1 | 1 | -1 |
⭐通过diff[]
数组可以求出num[]
的每一项,num[i] = diff[1] + diff[2] + ... + diff[i]
。
☕经过第一次区间修改1 3 1
:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
num | 2 | 3 | 3 | 1 | 2 | 1 | |
diff | 0 | 2 | 1 | 0 | -2 | 1 | -1 |
☕对区间1~3
的值全部加1,可以发现diff[]
数组只有diff[1]
与diff[4]
的值发生了改变,diff[1]+1
,diff[4]-1
。
☕经过第二次区间修改3 5 1
:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
num | 2 | 3 | 4 | 2 | 3 | 1 | |
diff | 0 | 2 | 1 | 1 | -2 | 1 | -2 |
☕经过第三次区间修改1 6 1
:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
num | 3 | 4 | 5 | 3 | 4 | 2 | |
diff | 0 | 3 | 1 | 1 | -2 | 1 | -2 |
⭐可以看到,对于每次区间修改l r c
,diff[]
只有两个位置会发生变化,那么我们只需要维护这两个位置就可以了,其中diff[l] = diff[l] + c
,diff[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] + " ");
}
}
}