• 算法--差分


    算法基础系列


    前言

    差分与前缀和是一家人,互为逆操作,类似于数学中的求导和积分
    前缀和的知识点,见之前的文章,点这里

    概念

    设两个数组 ab
    a数组是b数组的前缀和数组
    b数组是a数组的差分数组
    b[i] = a[i] - a[i-1]

    算法问题
    如何在已知数组a的情况下,对a'数组区间中的每一个数加上一个数c,如何快速求出?
    暴力思路:for循环,时间复杂度是 O ( n ) O(n) O(n)
    差分算法思路:只对区间两点进行加减,b[l] + cb[r] - c
    在这里插入图片描述

    这里的b[l] + c加上c之后,会影响其前缀和数组,使其后面的都加上了c,则需要消除区间外的影响,即在右区间减去c

    具体应用:
    输入一个长度为 n 的整数序列。接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。
    首先对序列进行读取,且读取的序列看作是"前缀和数组",方法是假定前缀和数组都是0,则差分数组(原数组)也是0,对前缀和数组进行加入操作,也就是 [1,1] + a[1] ,则得到了"前缀和数组",这一步是为了构造差分数组
    再根据题目要求读入操作区间,进行相应操作,最后对差分数组求出前缀和,即使答案

    步骤:先根据原数组构造差分数组,然后进行相应操作,最后求前缀和

    个人难点:怎么构造差分数组(根据原数组)?
    A:把输入的原数组看做是前缀和数组
    假定前缀和数组a(输入的原数组)和差分数组b都是0,对前缀和数组的[i,i]位置上进行插入操作(加上某个数),即这里加上原数组,即可得到对应的差分数组。配合代码理解

    代码模板

    一维差分

    给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c
    
    • 1

    二维差分

    给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
    S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
    
    • 1
    • 2

    差分(典型)

    传送门
    在这里插入图片描述
    代码:

    #include <iostream>
    
    using namespace std;
    
    const int N = 100010;
    
    int n, m;
    int a[N], b[N];
    
    void insert(int l, int r, int c)
    {
        b[l] += c;
        b[r + 1] -= c;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]); //输入初始数组
        // 初始前缀和为 0
        // 初始差分为 0
        for (int i = 1; i <= n; i++) //在区间[i,i]上加上a[i]
            insert(i, i, a[i]);      //构造差分数组
        while (m--)
        {
            int l, r, c;
            scanf("%d%d%d", &l, &r, &c);
            insert(l, r, c); //对差分数组进行相应操作
        }
        for (int i = 1; i <= n; i++) //对差分数组求前缀和 即 合并
        {
            b[i] += b[i - 1];
            printf("%d ", b[i]);
        }
        return 0;
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    【unity小技巧】unity事件系统创建通用的对象交互的功能
    如何下载 Apache + PHP + Mysql 集成安装环境并结合内网穿透工具实现公网访问内网服务
    CDN的应用场景
    JavaScript 67 JavaScript HTML DOM 67.7 JavaScript HTML DOM - 改变 CSS
    【Spring源码系列】Bean生命周期-实例化前
    Apache Doris 整合 FLINK CDC + Iceberg 构建实时湖仓一体的联邦查询
    SpringBoot getpost请求详解
    Flutter真机运行及模拟器运行
    AD教程 (十六)常用PCB封装的直接调用
    “谈谈如何理解索引?谈谈如何理解事物?”我来带你模拟面试~
  • 原文地址:https://blog.csdn.net/nefu_TSY/article/details/125629235