差分
一维差分
"""
# 查分适用场景
给你一串长度为n的数列a1,a2,a3......an,要求对a[L]~a[R]进行m次操作:
操作一:将a[L]~a[R]内的元素都加上P
操作二:将a[L]~a[R]内的元素都减去P
[参考](https://www.jianshu.com/p/fcb68475b5e4)
查分是前缀和的逆运算
原数组:a1, a2, a3, a4
查分数组:b1 = a1
b2 = a2 - a1
b3 = a3 - a2
b4 = a4 - a3
即满足:a1 = b1
a2 = b1 + b2
a3 = b1 + b2 + b3
a4 = b1 + b2 + b3 + b4
"""
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
/*
差分是前缀和的逆运算
原数组:a1, a2, a3, a4
查分数组:b1 = a1
b2 = a2 - a1
b3 = a3 - a2
b4 = a4 - a3
即满足:a1 = b1
a2 = b1 + b2
a3 = b1 + b2 + b3
a4 = b1 + b2 + b3 + b4
*/
var (
a []int
b []int
)
func add(l, r, p int) {
b[l-1] += p
if r < len(b) {
b[r] -= p
}
}
// 对于差分只有一个操作
func main() {
var reader = bufio.NewReader(os.Stdin)
var x = readArray(reader)
a = readArray(reader)
b = make([]int, x[0])
// 构造差分数组
// 题目将1作为下标开始
for i := 1; i < x[0]+1; i++ {
add(i, i, a[i-1])
}
// 处理操作
for i := 0; i < x[1]; i++ {
var op = readArray(reader)
add(op[0], op[1], op[2])
}
// 还原数组
a[0] = b[0]
for i := 1; i < x[0]; i++ {
a[i] = b[i] + a[i-1]
}
fmt.Println(nums2string(a, " "))
}
func nums2string(x []int, sep string) string {
var b strings.Builder
for i := 0; i < len(x); i++ {
b.WriteString(strconv.Itoa(x[i]))
b.WriteString(sep)
}
return b.String()
}
func readLine(reader *bufio.Reader) string {
var line, _ = reader.ReadString('\n')
return strings.TrimRight(line, "\n")
}
func readInt(reader *bufio.Reader) int {
var num, _ = strconv.Atoi(readLine(reader))
return num
}
func readArray(reader *bufio.Reader) []int {
var line = readLine(reader)
var strList = strings.Split(line, " ")
var nums = make([]int, 0)
var err error
var v int
for i := 0; i < len(strList); i++ {
if v, err = strconv.Atoi(strList[i]); err != nil {
continue
}
nums = append(nums, v)
}
return nums
}
/*
输入一个长度为n的整数序列。
接下来输入m个操作,每个操作包含三个整数l, r, c,表示将序列中[l, r]之间的每个数加上c。
请你输出进行完所有操作后的序列。
输入格式
第一行包含两个整数n和m。
第二行包含n个整数,表示整数序列。
接下来m行,每行包含三个整数l,r,c,表示一个操作。
输出格式
共一行,包含n个整数,表示最终序列。
数据范围
1≤n,m≤100000,
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
*/
二维差分
go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
var (
a [][]int
b [][]int
lx int
ly int
)
func add(x1, y1, x2, y2, p int) {
b[x1-1][y1-1] += p
b[x1-1][y2] -= p
b[x2][y1-1] -= p
b[x2][y2] += p
}
func main() {
var reader = bufio.NewReader(os.Stdin)
var x = readArray(reader)
lx = x[0]
ly = x[1]
// 原数组
a = make([][]int, x[0])
for i := 0; i < x[0]; i++ {
a[i] = readArray(reader)
}
// 初始化差分数组
b = make([][]int, x[0] + 1)
// 前缀和数组
var sums = make([][]int, x[0] + 1)
for i := 0; i < x[0] + 1; i++ {
b[i] = make([]int, x[1] + 1)
sums[i] = make([]int, x[1] + 1)
}
// 构造差分数组
for i := 0; i < x[0]; i++ {
for j := 0; j < x[1]; j++ {
add(i+1, j+1, i+1, j+1, a[i][j])
}
}
// 处理操作
for i := 0; i < x[2]; i++ {
var op = readArray(reader)
add(op[0], op[1], op[2], op[3], op[4])
}
// 还原数组
sums[0][0] = b[0][0]
for i := 1; i < x[0]; i++ {
sums[i][0] = sums[i-1][0] + b[i][0]
}
for i := 1; i < x[1]; i++ {
sums[0][i] = sums[0][i-1] + b[0][i]
}
//sums[1][0] = b[1][0] + b[0][0]
//sums[0][1] = b[0][1] + b[0][0]
for i := 1; i < x[0] + 1; i++ {
for j := 1; j < x[1] + 1; j++ {
sums[i][j] = sums[i][j-1] + sums[i-1][j] + b[i][j] - sums[i-1][j-1]
}
}
for i := 0; i < x[0]; i++ {
fmt.Println(nums2string(sums[i][:x[1]], " "))
}
}
func nums2string(x []int, sep string) string {
var b strings.Builder
for i := 0; i < len(x); i++ {
b.WriteString(strconv.Itoa(x[i]))
b.WriteString(sep)
}
return b.String()
}
func readLine(reader *bufio.Reader) string {
var line, _ = reader.ReadString('\n')
return strings.TrimRight(line, "\n")
}
func readInt(reader *bufio.Reader) int {
var num, _ = strconv.Atoi(readLine(reader))
return num
}
func readArray(reader *bufio.Reader) []int {
var line = readLine(reader)
var strList = strings.Split(line, " ")
var nums = make([]int, 0)
var err error
var v int
for i := 0; i < len(strList); i++ {
if v, err = strconv.Atoi(strList[i]); err != nil {
continue
}
nums = append(nums, v)
}
return nums
}
/*
输入一个n行m列的整数矩阵,再输入q个操作,每个操作包含五个整数x1, y1, x2, y2, c,其中(x1, y1)和(x2, y2)表示一个子矩阵的左上角坐标和右下角坐标。
每个操作都要将选中的子矩阵中的每个元素的值加上c。
请你将进行完所有操作后的矩阵输出。
输入格式
第一行包含整数n,m,q。
接下来n行,每行包含m个整数,表示整数矩阵。
接下来q行,每行包含5个整数x1, y1, x2, y2, c,表示一个操作。
输出格式
共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。
数据范围
1≤n,m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤c≤1000,
−1000≤矩阵内元素的值≤1000
输入样例:
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
输出样例:
2 3 4 1
4 3 4 1
2 2 2 2
*/
python
class Solution(object):
def __init__(self, matrix):
self.m = len(matrix) + 1
self.n = len(matrix[0]) + 1
x = len(matrix) + 10
y = len(matrix[0]) + 10
self.nums = [[0] * y for _ in range(x)]
for i in range(len(matrix)):
for j in range(len(matrix[0])):
self.add(i + 1, j + 1, i + 1, j + 1, matrix[i][j])
def add(self, x1, y1, x2, y2, c):
self.nums[x1][y1] += c
self.nums[x2 + 1][y1] -= c
self.nums[x1][y2 + 1] -= c
self.nums[x2 + 1][y2 + 1] += c
def query(self):
ans = [[0] * self.n for _ in range(self.m)]
for i in range(1, self.m):
for j in range(1, self.n):
ans[i][j] = ans[i][j - 1] + ans[i - 1][j] - ans[i - 1][j - 1] + self.nums[i][j]
# print(ans)
for xx in ans[1:]:
print(" ".join([str(x) for x in xx[1:]]))
if __name__ == '__main__':
n, m, q = [int(x) for x in input().split(" ")]
xx = [[0] * m for _ in range(n)]
for i in range(n):
xx[i] = [int(x) for x in input().split(" ")]
S = Solution(xx)
for _ in range(q):
qq = [int(x) for x in input().split(" ")]
S.add(qq[0], qq[1], qq[2], qq[3], qq[4])
S.query()
最后更新于
这有帮助吗?