一维差分
睡不醒的鲤鱼 2021-10-24 常用算法 差分
一、算法思想
差分定义:前缀和的逆运算。
当给定一个数组 A,我们需要构造一个数组 B,使得 A 是 B 的前缀和,此时我们称 B 是 A 的差分。
1.1 计算方法
bi=ai−ai−1 说明
一般不会用这种构造方法,B 数组的构造可以看作是全 0 的 A 数组进行 n 次的 [i,i] 的元素累加操作,这样可以将差分的构造与应用进行统一。
1.2 作用
根据差分的定义,O(n) 的时间内就可以通过 B 数组还原出 A 数组,因此可以将它们看作是等价的。
那么来看这样的操作,对 A 数组中 [l,r] 区间内的元素加上 c。
- 如果在 A 数组操作,那么时间复杂度是 O(n) 的;
- 如果在 B 数组操作,那么就可以在 O(1) 时间内完成,具体方法如下:
b[l] += c;
b[r + 1] -= c;
1
2
二、算法模板
Go
type Difference1D struct {
diff []int
n int
}
func NewDifference1D(n int) *Difference1D {
return &Difference1D{
diff: make([]int, n+2),
n: n,
}
}
func (df *Difference1D) insert(l, r, c int) {
df.diff[l] += c
df.diff[r+1] -= c
}
func (df *Difference1D) final() (ans []int) {
ans = make([]int, df.n+1)
for i := range ans {
ans[i] = df.diff[i]
}
for i := 1; i <= df.n; i++ {
ans[i] += ans[i-1]
}
ans = ans[1:]
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
三、代码实战
AcWing 0797
题目:差分
输入一个长度为 n 的整数序列。
接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。
请你输出进行完所有操作后的序列。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数数列。
接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。
输出格式
共一行,包含 n 个整数,表示最终序列。
数据范围
1≤n,m≤105 1≤l≤r≤n −1000≤c≤1000 −1000≤整数序列中元素的值≤1000 输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
解答代码:
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int a[N], b[N];
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
insert(i, i, a[i]);
}
while (m--) {
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
insert(l, r, c);
}
for (int i = 1; i <= n; i++) {
b[i] += b[i - 1];
printf("%d ", b[i]);
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
import (
"bufio"
. "fmt"
"io"
"os"
)
type Difference1D struct {
diff []int
n int
}
func NewDifference1D(n int) *Difference1D {
return &Difference1D{
diff: make([]int, n+2),
n: n,
}
}
func (df *Difference1D) insert(l, r, c int) {
df.diff[l] += c
df.diff[r+1] -= c
}
func (df *Difference1D) final() (ans []int) {
ans = make([]int, df.n+1)
for i := range ans {
ans[i] = df.diff[i]
}
for i := 1; i <= df.n; i++ {
ans[i] += ans[i-1]
}
ans = ans[1:]
return
}
func run(_r io.Reader, out io.Writer) {
in := bufio.NewReader(_r)
var n, m int
Fscan(in, &n, &m)
df := NewDifference1D(n)
var x int
for i := 0; i < n; i++ {
Fscan(in, &x)
df.insert(i+1, i+1, x)
}
for i := 0; i < m; i++ {
var l, r, c int
Fscan(in, &l, &r, &c)
df.insert(l, r, c)
}
ans := df.final()
for _, num := range ans {
Fprintf(out, "%d ", num)
}
}
func main() {
run(os.Stdin, os.Stdout)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71