🤵♂️ 个人主页: @AI_magician
📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。
👨💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱🏍
@toc
差分和前缀和其实是互逆的,为什么呢🙌,我们看到最后就会明白
一维差分是一维前缀和的原数组,那么二维差分就是二维前缀和的原数组。
在二维区间内进行频繁加减操作时,可以使用二维差分数组来优化时间复杂度。具体步骤如下:
假设原数组为 A
,大小为 m x n
,差分数组为 D
,大小为 (m+1) x (n+1)
,初始化为0,此时通过操作差分数组获取原数组,若是要从原数组得到差分数组,则公式为
$$
Di = Ai - Ai-1 - Ai + Ai-1
$$
要在矩形区域 (x1, y1)
到 (x2, y2)
内增加 val
,更新 差分数组:
D[x1][y1] += val
D[x1][y2+1] -= val
D[x2+1][y1] -= val
D[x2+1][y2+1] += val
数学容斥定理:
<img src="https://i-blog.csdnimg.cn/img\_convert/e7914941e954d300c69bde74fc6cf21a.png" alt="image-20250130193637024" style="zoom: 50%;" />
c++ 模板
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3 + 10;
int a[N][N], b[N][N];
# 注意初始化最小要为n+2
void insert(int x1, int y1, int x2, int y2, int c) {
b[x1][y1] += c;
b[x2 + 1][y1] -= c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y2 + 1] += c;
}
int main() {
int n, m, q;
cin >> n >> m >> q;
// 读取矩阵a
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
// 初始化差分数组b
// 通过 insert(i, j, i, j, a[i][j]) 将每个元素的值转化为差分数组 b 的初始值。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
insert(i, j, i, j, a[i][j]);
}
}
// 处理查询
while (q--) {
int x1, y1, x2, y2, c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1, y1, x2, y2, c);
}
// 计算最终的b矩阵
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
b[i][j] += b[i-1][j] + b[i][j-1] - b[i-1][j-1]; // 二维前缀和
}
}
// 输出结果
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
printf("%d ", b[i][j]);
}
printf("\n");
}
return 0;
}
蓝桥杯 棋盘
n×n 大小的棋盘,一开始棋盘上全都是白子。小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)。请输出所有操作做完后棋盘上每个棋子的颜色。
class Solution:
def solve():
# 输入棋盘大小 n 和操作次数 m
n, m = list(map(int, input().split(" ")))
# 构造差分数组,大小为 (n+2) x (n+2),避免边界问题
diff = [[0 for _ in range(n+2)] for _ in range(n+2)]
# 处理每个操作,更新差分数组
for _ in range(m):
x1, y1, x2, y2 = list(map(int, input().split(" ")))
# 更新差分数组的四个角
diff[x1][y1] += 1 # 左上角 +1
# if y2 + 1 <= n: # 避免越界
diff[x1][y2 + 1] -= 1 # 右上角 -1
# if x2 + 1 <= n: # 避免越界
diff[x2 + 1][y1] -= 1 # 左下角 -1
# if x2 + 1 <= n and y2 + 1 <= n: # 避免越界
diff[x2 + 1][y2 + 1] += 1 # 右下角 +1
# 构造棋盘,存储最终每个位置的颜色
chess = [[0 for _ in range(n)] for _ in range(n)]
# 通过差分数组计算每个位置的颜色
for i in range(1, n+1): # 遍历行
for j in range(1, n+1): # 遍历列
# 计算当前位置的翻转次数
diff[i][j] += diff[i-1][j] + diff[i][j-1] - diff[i-1][j-1]
# 根据翻转次数的奇偶性决定颜色
chess[i-1][j-1] = 0 if diff[i][j] % 2 == 0 else 1 # 对应chess
# diff[i][j] = 0 if diff[i][j] % 2 == 0 else 1 这种方式要额外处理数组
# 输出棋盘
# arr = [0 for _ in range(n)]
# for i, li in enumerate(diff[1:n+1]):
# arr[i] = li[1:n+1]
# print(arr)
# 输出棋盘
for row in chess:
# 将每行的列表转换为字符串并输出
print(''.join(map(str, row)))
# 调用 solve 方法
Solution.solve()
可以总结到,差分适用于记录区间频次,和区间有关的频次都要考虑到
🤞到这里,如果还有什么疑问🤞
🎩欢迎私信博主问题哦,博主会尽自己能力为你解答疑惑的!🎩
🥳如果对你有帮助,你的赞是对博主最大的支持!!🥳
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。