蓝桥杯第九讲--差分【例/习题】

简介: 蓝桥杯第九讲--差分【例/习题】

前言

蓝桥杯官网:蓝桥杯大赛——全国大学生TMT行业赛事

✨本博客讲解 蓝桥杯C/C++ 备赛所涉及算法知识,此博客为第九讲:差分【例/习题】

本篇博客所包含习题有:

👊差分

👊差分矩阵


有关差分的内容细致讲解见博文:差分

有关差分的模板见博文:差分算法模板


博客内容以题代讲,通过讲解题目的做法来帮助读者快速理解算法内容,需要注意:学习算法不能光过脑,更要实践,请读者务必自己敲写一遍本博客相关代码!!!


差分

题目要求

题目描述:

image.png

输入格式:

image.png

输出格式:

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

数据范围:

image.png

输入样例:

6 3

1 2 2 1 2 1

1 3 1

3 5 1

1 6 1

输出样例:

3 4 5 3 4 2

思路分析

一维差分的模板题,对于差分你可以理解成为前缀和的逆运算,差分数组的构造方法为:

s数组是差分数组,a数组是原数组
s[0] = 0, a[0] = 0;
s[1] = a[1] - a[0];
s[2] = a[2] - a[1];
...
s[n] = a[n] - a[n - 1];

令 a 数组在 [ l , r ]  的区间内加上一个数 c可以用差分的思维:

s[l] += c;
s[r + 1] -= c;

然后对差分数组做一遍前缀和即可。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int a[N], s[N];
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
    // 处理差分数组
    for (int i = 1; i <= n; i ++ ) s[i] = a[i] - a[i - 1];
    while (m -- )
    {
        int l, r, c;
        scanf("%d%d%d", &l, &r, &c);
        s[l] += c, s[r + 1] -= c;
    }
    for (int i = 1; i <= n; i ++ ) 
    {
        s[i] += s[i - 1];
        printf("%d ", s[i]);
    }
    return 0;
}

差分矩阵

题目要求

题目描述:

image.png

输入格式:

image.png

输出格式:

共 n  行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

数据范围:

image.png

输入样例:

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

思路分析

对于二维差分数组,你可以这么去理解:如果前缀和的二维矩阵上的某一点是影响从矩阵左上角到该点内的数,那么差分数组矩阵就是影响从这一点到矩阵右下角,往 a 数组(二维) ( x 1 , y 1 )【左上角】和 ( x 2 , y 2 ) 【右下角】的矩阵内加上一个数 c可用差分:

s[x1][y1] += c;
s[x2 + 1][y1] -= c;
s[x1][y2 + 1] -= c;
s[x2 + 1][y2 + 1] += c;

然后再计算一遍前缀和数组,即可得到结果,注意我们的前缀和模板应该是:

s[i, j] = s[i, j - 1] + s[i - 1, j] - s[i - 1, j - 1] + a[i, j];

但此时的 s [ i , j ]其实就是一个值,即也为 a [ i , j ],故把差分数组变为前缀和数组为:

s[i][j] += s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int a[N][N], s[N][N];
void insert(int x1, int y1, int x2, int y2, int c)
{
    s[x1][y1] += c;
    s[x2 + 1][y1] -= c;
    s[x1][y2 + 1] -= c;
    s[x2 + 1][y2 + 1] += c;
}
int main()
{
    int n, m, q;
    scanf("%d%d%d", &n, &m, &q);
    for (int i = 1; i <= n; i ++ ) 
        for (int j = 1; j <= m; j ++ ) 
            scanf("%d", &a[i][j]);
    // 处理差分数组
    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;
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
        insert(x1, y1, x2, y2, c);
    }
    // 计算前缀和数组
    for (int i = 1; i <= n; i ++ ) 
        for (int j = 1; j <= m; j ++ ) 
            s[i][j] += s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];
    for (int i = 1; i <= n; i ++ ) 
    {
        for (int j = 1; j <= m; j ++ ) 
            printf("%d ", s[i][j]);
        puts("");
    }
    return 0;   
}




目录
相关文章
|
移动开发 算法 机器人
[蓝桥杯] 二分与前缀和习题练习
又来更新了。二分与前缀和是蓝桥杯比较常考的内容,所以我们要多加练习这方面的习题。二分与前缀和的难度相对来说不算大,我们应该掌握其关键要点。
102 0
|
算法
[蓝桥杯] 递归与递推习题训练
蓝桥杯比赛只有四十天左右啦,最近会按照模块更新一些有关蓝桥杯算法题。学习算法不仅仅是为了参见比赛,更是以后找工作的一个敲门砖。废话不多说,我们直接看题。
77 0
《蓝桥杯每日一题》差分·Acwing3729. 改变数组元素
《蓝桥杯每日一题》差分·Acwing3729. 改变数组元素
56 0
《蓝桥杯每日一题》差分·Acwing3729. 改变数组元素
|
存储 算法 Java
【数据结构】蓝桥杯常见习题(二)
【数据结构】蓝桥杯常见习题(二)
10971 0
|
人工智能 移动开发 机器人
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
蓝桥杯AcWing 题目题解 - 二分与前缀和、差分
149 0
|
人工智能 测试技术
[蓝桥杯 2022 省 A] 求和——前缀和,差分
[蓝桥杯 2022 省 A] 求和——前缀和,差分
75 0
|
存储 Java C#
【数据结构】蓝桥杯常见习题(一)
【数据结构】蓝桥杯常见习题(一)
644 0
|
算法 Java vr&ar
【差分数组】还不懂差分数组?蓝桥杯算法模板题小明的彩灯解析
文章目录 1.算法背景 2.差分数组 2.1 什么是差分数组? 2.2 差分数组的性质 3 例题——小明的彩灯 3.1 题目分析 3.2 参考代码(Java) 3.3 实现结果
【差分数组】还不懂差分数组?蓝桥杯算法模板题小明的彩灯解析
|
算法 C++
蓝桥杯第十五讲--复杂dp【习题】
蓝桥杯第十五讲--复杂dp【习题】
245 0
蓝桥杯第十五讲--复杂dp【习题】
|
算法 C语言 C++
蓝桥杯第十四讲--数论【习题】
蓝桥杯第十四讲--数论【习题】
169 0
蓝桥杯第十四讲--数论【习题】