一维差分

2021-10-24 常用算法 差分

# 一、算法思想

差分定义:前缀和的逆运算。

当给定一个数组 AA,我们需要构造一个数组 BB,使得 AABB 的前缀和,此时我们称 BBAA 的差分。

# 1.1 计算方法

bi=aiai1b_i = a_i - a_{i-1}

说明

一般不会用这种构造方法,BB 数组的构造可以看作是全 00AA 数组进行 nn 次的 [i,i][i,i] 的元素累加操作,这样可以将差分的构造与应用进行统一。

# 1.2 作用

根据差分的定义,O(n)O(n) 的时间内就可以通过 BB 数组还原出 AA 数组,因此可以将它们看作是等价的。

那么来看这样的操作,对 AA 数组中 [l,r][l,r] 区间内的元素加上 cc

  • 如果在 AA 数组操作,那么时间复杂度是 O(n)O(n) 的;
  • 如果在 BB 数组操作,那么就可以在 O(1)O(1) 时间内完成,具体方法如下:
b[l] += c;
b[r + 1] -= c;
1
2

# 二、算法模板

Go

type Difference1D struct {
    diff []int
    n    int
}

// NewDifference1D 初始化一维差分数组
func NewDifference1D(n int) *Difference1D {
    return &Difference1D{
        diff: make([]int, n+2),
        n:    n,
    }
}

// 给 l 到 r 区间内的元素加上 c
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


题目:差分

输入一个长度为 nn 的整数序列。

接下来输入 mm 个操作,每个操作包含三个整数 l,r,cl,r,c,表示将序列中 [l,r][l,r] 之间的每个数加上 cc

请你输出进行完所有操作后的序列。

输入格式

第一行包含两个整数 nnmm

第二行包含 nn 个整数,表示整数数列。

接下来 mm 行,每行包含三个整数 llrrcc,表示一个操作。

输出格式

共一行,包含 nn 个整数,表示最终序列。

数据范围

1n,m1051 \le n, m \le 10^5
1lrn1 \le l \le r \le n
1000c1000-1000 \le c \le 1000
1000整数序列中元素的值1000-1000 \le \text{整数序列中元素的值} \le 1000

输入样例:

6 3

1 2 2 1 2 1

1 3 1

3 5 1

1 6 1

输出样例:

3 4 5 3 4 2

解答代码:

    Last Updated: 2023-01-28 4:31:25