首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【蓝桥杯 | 备赛秘籍】真题解析之差分数组—一维、二维差分一套拿下,附蓝桥杯真题和代码实战!(下)

【蓝桥杯 | 备赛秘籍】真题解析之差分数组—一维、二维差分一套拿下,附蓝桥杯真题和代码实战!(下)

原创
作者头像
计算机魔术师
发布2025-02-07 07:44:14
发布2025-02-07 07:44:14
22100
代码可运行
举报
文章被收录于专栏:计算机魔术师计算机魔术师
运行总次数:0
代码可运行

🤵‍♂️ 个人主页: @AI_magician

📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。

👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍

@toc

差分和前缀和其实是互逆的,为什么呢🙌,我们看到最后就会明白

差分数组

二维数组

一维差分是一维前缀和的原数组,那么二维差分就是二维前缀和的原数组。

在二维区间内进行频繁加减操作时,可以使用二维差分数组来优化时间复杂度。具体步骤如下:

  1. 初始化二维差分数组

假设原数组为 A,大小为 m x n,差分数组为 D,大小为 (m+1) x (n+1),初始化为0,此时通过操作差分数组获取原数组,若是要从原数组得到差分数组,则公式为

$$

Di = Ai - Ai-1 - Ai + Ai-1

$$

  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%;" />

  1. 计算前缀和

c++ 模板

代码语言:python
代码运行次数:0
运行
复制
#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 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)。请输出所有操作做完后棋盘上每个棋子的颜色。

代码语言:python
代码运行次数:0
运行
复制
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()

可以总结到,差分适用于记录区间频次,和区间有关的频次都要考虑到

代码语言:txt
复制
							  🤞到这里,如果还有什么疑问🤞
						🎩欢迎私信博主问题哦,博主会尽自己能力为你解答疑惑的!🎩
						 	 🥳如果对你有帮助,你的赞是对博主最大的支持!!🥳

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 差分数组
    • 二维数组
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档