一维差分,二维差分(详解+例题)

news2024/11/21 1:44:25

一、一维差分

1.1、解释:

        设数列an,记an为数列bn的前n项和

        原数组:a[1],a[2],a[3],a[4]..................a[n];

   构造一个数组b:b[1],b[2],b[3],b[4].................b[i];

使得a[i] = b[1] + b[2] + b[3] + ........ + b[i];

也就是说,a数组是b数组的前缀和数组,反过来我们把b数组,叫做a数组的差分数组。换句话说,每一个a[i]都是b数组中从头开始的区间和。

1.2、样例:


a[0] = 0
b[1] = a[1];
b[2] = a[2] - a[1];
b[3] = a[3] - a[2];
...           .....
b[i] = a[i] - a[i-1];

1.3、作用: 

  • 让一个序列中某个区间内的所有值均加上或减去一个常数C。

  • 可以将对a数组任意区间的同一操作从O(n)优化到O(1)。

我们只需要让差分数组b中,区间[l,r]中的所有值都加上常数C,
b[l] += c;
b[r+1] -= c;

解析:

a[l] = b[1]+b[2]+...+b[l-1]+b[l]; 

......                                 .......;

a[r] =  b[1]+b[2]+...b[l]+...+b[r]; 

a[r+1] = b[1]+b[2]+...b[l]+...+b[r]+b[r+1];

我们只向让[l,r]之间的和加C不想让后面r+1之后的也加C,所以我们让b[r+1] -= c;

1.4、核心代码:

  •   对a数组区间[l,r]同时加上c的操作可转化为:
  • void insert(int l, int r, int c)
    {
        b[l] += c;
        b[r+1] -= c;
    }
    //求前缀和
    for(int i = 1; i <= n; i++)
    {
        b[i] += b[i-1];
        printf("%d ",b[i]);
    }

    1.5、例题:此题来源于Acwing

AC代码如下:

#include<iostream>

using namespace std;

const int N = 100010;
int a[N],b[N];
int n,m;

//构造差分数组
void insert(int l,int r,int c)
{
    b[l] = b[l] + c;
    b[r+1] = b[r+1] - c;
}

int main()
{
    scanf("%d %d", &n, &m);
    for(int i=1;i<=n;i++) scanf("%d ", &a[i]);;
    //默认b数组是0,开始构造差分数组
    /*举个例子:
    例如:样例中的a数组 1 2 2 1 2 1
    1,1,a[1]传入,b[1] = b[1] + a[1];
    b[2] = b[2] - a[1];
    这是一次传入,第二次:b[2] = b[2] + a[2] ---->这里b[2] = -a[1] ---->正好满足差分概念
    b[3] = b[3] - a[2]
    */
    for(int i=1;i<=n;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] + b[i-1];
    }
    
    for(int i=1;i<=n;i++) printf("%d ",b[i]);
    return 0;
}

 题目样例解析:

  • 样例:

    比如 : 1 2 2 1 2 1(原数组) 下标从1开始

    1 1 0 -1 1 -1(差分数组)构造之后的

  • 我们通过上面两种方法进行构造,第二种方法,我们可以这么理解,假定a数组和b数组最开始为0,对于每一个a数组

    和b数组最开始为0,对于每一个a[i] 相当于插入一个数,进行计算,具体例子代码注释上有。


二、二维差分 

 1.1、图解:

如图上图,我们想要求小的黑色方块+c后的结果,首先,根据公式b[x1] [y1] += c ,改变的从 (x1,y1)这个点到右下角的所有值都加C

我们想要是只让小黑方块里加C即可,其他位置不变,那么我们就需要类比一维差分让画虚线的部分减c,下面是黑阴影面积,右面是紫色阴影面积,所以我们要让(紫色阴影面积部分)b [x1] [y2+1] += c, 和 (黑色阴影面积)b [x2+1] [y1] += c, 然后我们可以发现重叠的部分多加了一次C,所以我们再让重叠部分减去C即可,(重叠部分)b [x2+1] [y2+1] += c,用来抵消,这样正好其他的地方都不会发生变化。

由此,我们可以推出公式:

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

1.2、例题:此题来源于ACwing

AC代码如下: 

#include<iostream>

using namespace std;

const int N = 1010;
int b[N][N],a[N][N];

//构造差分数组
void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1] += c;
    b[x1][y2+1] -= c;
    b[x2+1][y1] -= c;
    b[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]);
        }
    }
    //假定a数组和b数组都是0,去构造差分数组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;
        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++)
        {
            b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + b[i][j];
        }
    }
    //输出
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            printf("%d ",b[i][j]);
        }
        puts("");
    }
    return 0;
}

关于构造b数组代码解释:

for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            insert(i,j,i,j,a[i][j]);
        }
    }

 我们可以先设想a数组为空,那么b数组一开始也为空,但实际上数组a并不为空,因为我们每一次让b数组以(i,j)为左上角到以(i,j)为右下角面积内元素(其实就是一个小方块面积)插入c=a[i][j]。


以上综合大佬博客和个人理解所整理,如果有错的地方,欢迎指出~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1434385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot:配置相关知识点

SpringBoot&#xff1a;多环境配置 配置知识点demo&#xff1a;点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 一、SpringBootApplication SpringBootApplication 来标注一个主程序类&#xff0c;说明这是一个Spring Boot应用&#xff0c;运行这个类的main方法来…

并查集实现|并查集在相关题目中的应用|手撕数据结构专栏

前言 那么这里博主先安利一下一些干货满满的专栏啦&#xff01; 高质量干货博客汇总http://t.csdnimg.cn/jdQXqGit企业开发控制理论和实操http://t.csdnimg.cn/PyPJeDocker从认识到实践再到底层原理http://t.csdnimg.cn/G6Inp手撕数据结构http://t.csdnimg.cn/XeyJn 这里是很…

IT行业证书的获取与价值:提升职业竞争力的关键

目录 IT行业证书的价值和作用 1. Cisco&#xff08;思科&#xff09;认证&#xff08;如CCNA、CCNP、CCIE&#xff09;&#xff1a; 2. 微软认证&#xff08;如MCSA、MCSE、MCSD&#xff09;&#xff1a; 3. 计算机网络技术&#xff08;CompTIA Network、CompTIA Security&a…

智慧城市:打造低碳未来,引领城市数字化转型新篇章

在“万物皆可数字化”的新时代浪潮下&#xff0c;智慧城市作为未来城市发展的先锋方向&#xff0c;正在以前所未有的速度和规模重塑我们的城市面貌。 智慧城市不仅是一个技术革新的标志&#xff0c;更是城市治理、民生服务等领域全面升级的重要引擎。 一、智慧城市的多元应用领…

C++之字符串

C风格字符串 字符串处理在程序中应用广泛&#xff0c;C风格字符串是以\0&#xff08;空字符&#xff09;来结尾的字符数组。对字符串进行操作的C函数定义在头文件<string.h>或中。常用的库函数如下&#xff1a; //字符检查函数(非修改式操作) size_t strlen( const char …

sqli.labs靶场(54-65关)

54、第五十四关 提示尝试是十次后数据库就重置&#xff0c;那我们尝试union 原来是单引号闭合 id-1 union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schemadatabase()) -- 数据库&#xff1a;challenges&#xff0c…

Spring5系列学习文章分享---第六篇(框架新功能系列+整合日志+ @Nullable注解 + JUnit5整合)

目录 **Spring5** 框架新功能系列一Spring 5.0 框架自带了通用的日志封装Spring5 **框架核心容器**支持Nullable **注解****Spring5** **核心容器支持函数式风格** GenericApplicationContext**Spring5** **支持整合** JUnit5感谢阅读 开篇: 欢迎再次来到 Spring 5 学习系列&am…

图解支付-金融级密钥管理系统:构建支付系统的安全基石

经常在网上看到某某公司几千万的个人敏感信息被泄露&#xff0c;这要是放在持牌的支付公司&#xff0c;可能就是一个非常大的麻烦&#xff0c;不但会失去用户的信任&#xff0c;而且可能会被吊销牌照。而现实情况是很多公司的技术研发人员并没有足够深的安全架构经验来设计一套…

【2024美赛E题】985博士解题思路分析(持续更新中)!

【2024美赛E题】985博士解题思路分析&#xff01; 加群可以享受定制等更多服务&#xff0c;或者搜索B站&#xff1a;数模洛凌寺 联络组织企鹅&#xff1a;936670395 以下是E题老师的解题思路&#xff08;企鹅内还会随时更新文档&#xff09;&#xff1a; 2024美赛E题思路详解…

Unity3d Cinemachine篇(完)— TargetGroup

文章目录 前言使用TargetGroup追随多个模型1. 创建二个游戏物体2. 创建TargetGroup相机3. 设置相机4. 完成 前言 上一期我们简单的使用了ClearShot相机&#xff0c;这次我们来使用一下TargetGroup 使用TargetGroup追随多个模型 1. 创建二个游戏物体 2. 创建TargetGroup相机 3…

1-3 动手学深度学习v2-线性回归的从零开始实现-笔记

手动创建训练数据集 根据带有噪声的线性模型构造一个人造数据集。我们使用线性模型参数 w [ 2 , − 3.4 ] T \pmb{w} [2,-3.4]^{T} w[2,−3.4]T、 b 4.2 b 4.2 b4.2和噪声项 ϵ \epsilon ϵ生成数据集及其标签&#xff1a; y X w b ϵ \pmb{y} \pmb{Xw}b\epsilon yXw…

挑战!贪吃蛇小游戏的实现(1)

引言 相信大家都玩过贪吃蛇这个游戏&#xff01; 玩家控制一个不断移动的蛇形角色&#xff0c;在一个封闭空间内移动。随着时间推进&#xff0c;这个蛇形角色会逐渐增长&#xff0c;通常是通过吞食屏幕上出现的物品&#xff08;如点或者其他标志&#xff09;来实现。每当贪吃…

XML:可扩展标记语言

XML&#xff1a;可扩展标记语言 主要内容 XML介绍DTDXSDDOM解析SAX解析 学习目标 知识点要求XML介绍掌握DTD掌握XSD掌握DOM解析掌握SAX解析掌握 一、XML介绍 1. 简介 XML&#xff08;Extensible Markup Language&#xff09;可扩展标记语言。严格区分大小写。 2. XML和…

肿瘤微环境各种浸润细胞及maker(学习)

目录 Tumor Infiltrating Leukocytes&#xff08;肿瘤浸润性白细胞&#xff09; TISCH2数据库收录的TIL 免疫细胞的分类 28种不同免疫细胞类型 Tumor Infiltrating Leukocytes&#xff08;肿瘤浸润性白细胞&#xff09; Gene expression markers of Tumor Infiltrating Le…

关于Linux和消息队列常见的十道面试题

实际工作中如何排查CPU飙升问题&#xff1f; 在实际工作中&#xff0c;我们可以通过以下步骤来排查CPU飙升的问题&#xff1a; 使用系统监控工具&#xff1a;首先&#xff0c;我们可以使用系统监控工具&#xff0c;如top命令&#xff0c;来查看所有进程占系统CPU的排序。这样可…

vue element 组件 form深层 :prop 验证失效问题解决

此图源自官网 借鉴。 当我们简单单层验证的时候发现是没有问题的&#xff0c;但是有的时候可能会涉及到深层prop&#xff0c;发现在去绑定的时候就不生效了。例如我们在form单里面循环验证&#xff0c;在去循环数据验证。 就如下图的写法了 :prop"pumplist. i .device…

LeetCode、216. 组合总和 III【中等,组合型枚举】

文章目录 前言LeetCode、216. 组合总和 III【中等&#xff0c;组合型枚举】题目类型与分类思路 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖…

一篇文章认识Vue3

Vue 3 介绍 Vue3 于 2022 年 2 月 7 日星期一成为新的默认版本&#xff01;Vue3 性能更高&#xff0c;体积更小Vue3 在经过一年的迭代后&#xff0c;越来越好用。 官方文档&#xff1a; vue3官方文档&#xff1a;vuejs.org/vue3中文文档&#xff1a;v3.cn.vuejs.org/vue3预发…

挂耳式耳机什么牌子的好?年度最值得入手的挂耳式耳机推荐

近年来耳机市场发展迅猛&#xff0c;蓝牙耳机品类日益增多。而挂耳式耳机尤其火爆&#xff0c;得益于其出色的佩戴体验&#xff0c;赢得了众多消费者的青睐。市场上挂耳式耳机的品牌种类繁多&#xff0c;让许多消费者在选择时感到困惑&#xff0c;挂耳机耳机什么牌子的好&#…

【React】redux状态管理、react-redux状态管理高级封装模块化

【React】react组件传参、redux状态管理 一、redux全局状态管理1、redux概述2、redux的组成1.1 State-状态1.2 Action-事件1.3 Reducer1.4 Store 3、redux入门案例1.1 前期准备1.2 构建store1.2.1 在src下新建store文件夹1.2.2 在store文件夹下新建index.ts文件1.2.3 在index.t…