差分详细讲解(C++)

2023-11-04

每日一句:平凡的我在人多的地方曾极力小心翼翼, 但不知从何时起 ,我不太在意别人的目光了。比起被人觉得是个怪人,我现在更害怕浪费时间。


一、一维差分

差分就是前缀和的逆运算,如果你不懂什么是前缀和,看这里->前缀和详解

数组a:a[1], a[2], a[3], a[n]
数组b : b[1] ,b[2] , b[3], b[i]
使得 a数组是b数组的前缀和,b数组是a数组的差分
a[i] = b[1] + b[2] + …+ b[i]

数字来看的话就是这样的:
a数组1 3 7 5 2
b数组1 2 4 -2 -3
Sumb数组1 1+2 1+2+4 1+2+4-2 1+2+4-2-3
----------也就是1 3 7 5 2跟原数组还是相同的
a是b的前缀和,b是a的差分.

那么,问题来了,差分有什么用呢?

当你把一个区间[L,R]的数都加上或减去某一个数x的时候,该怎末做呢?第一时间想到的肯定是暴力做法,输入LR区间,然后for循环,直接暴力解决,确实暴力解法能解决很多事情,但是时间复杂度很高,为O(n),如果想进行m次区间加上或减去x的操作呢?每次都遍历LR区间,那么时间复杂度就更高了O(n*m).这个时候,就有人对其优化,想出来了一种名为差分的解法,差分解法呢,有一个公式:[L,R] + X <==>差分数组[L] + X,差分数组[R+1] - X;
那么,这个公式是怎么来的?
在这里插入图片描述
下面看一道例题:

输入一个长度为 n 的整数序列。

接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。

请你输出进行完所有操作后的序列。

输入格式

第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数序列。

接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。

输出格式

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

数据范围

1≤n,m≤100000, 1≤l≤r≤n, −1000≤c≤1000, −1000≤整数序列中元素的值≤1000

输入样例:

—6 3
—1 2 2 1 2 1
—1 3 1
—3 5 1
—1 6 1

输出样例:

3 4 5 3 4 2

1.先输入数组

	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}

然后把原数组a,变成差分数组b

	void insert(int l, int r, int c)
	{
		b[l] += c;
		b[r + 1] -= c;
	}


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

对差分数组进行m次操作

	while (m--)
	{
		int l, r, c;
		cin >> l >> r >> c;
		insert(l, r, c);
	}

最后,将差分数组变回原数组

	for (int i = 1; i <= n; i++)
	{
		b[i] += b[i - 1];
		cout << b[i] << ' ';
	}

总代码

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int a[N];

int b[N];

void insert(int l, int r, int c)
{
	b[l] += c;
	b[r + 1] -= c;
}

int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}

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

	while (m--)
	{
		int l, r, c;
		cin >> l >> r >> c;
		insert(l, r, c);
	}

	for (int i = 1; i <= n; i++)
	{
		b[i] += b[i - 1];
		cout << b[i] << ' ';
	}


	return 0;
}

题目来源acwing799

二、二维差分

二维差分也就是二维前缀和的逆运算,其构造差分的过程和构造一维差分的过程差不多类似.在这里主要说一下构造过程:

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;
}

标红区区域便是x1,y1进行区间加或减操作的区域

在这里插入图片描述

黄色和咖啡色区域便是x2+1,y1和x1,y2+1的区间,而有x2+1,y2+1的区间是重叠的部分,也就是说,在 b[x2 + 1][y1] -= c; b[x1][y2 + 1] -= c;这两部中,x2+1,y2+1被多减了一次,所以要把这部分还回去,也就是这一步 b[x2 + 1][y2 + 1] += c;

在这里插入图片描述

下面看一到例题

输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c,其中 (x1,y1) 和(x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。

每个操作都要将选中的子矩阵中的每个元素的值加上 c。

请你将进行完所有操作后的矩阵输出。

输入格式

第一行包含整数 n,m,q。

接下来 n 行,每行包含 m 个整数,表示整数矩阵。

接下来 q 行,每行包含 5 个整数 x1,y1,x2,y2,c,表示一个操作 。

输出格式

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

数据范围

1≤n,m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤c≤1000,
−1000≤矩阵内元素的值≤1000

输入样例

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

代码

#include <iostream>

using namespace std;

const int N = 1010;

int n, m, q;
int a[N][N], b[N][N];

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()
{
    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;
        cin >> 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];

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++) printf("%d ", b[i][j]);
        puts("");
    }

    return 0;
}

题目来源acwing800

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

差分详细讲解(C++) 的相关文章

  • IEnumerable 的 String.Join(string, string[]) 的类似物

    class String包含非常有用的方法 String Join string string 它从数组创建一个字符串 用给定的符号分隔数组的每个元素 但一般来说 它不会在最后一个元素之后添加分隔符 我将它用于 ASP NET 编码 以用
  • MFC CList 支持复制分配吗?

    我在 MSVC 中查找了 CList 定义afxtempl h http www cppdoc com example mfc classdoc MFC AFXTEMPL H html并记录在MSDN http msdn microsoft
  • C# 处理标准输入

    我目前正在尝试通过命令行断开与网络文件夹的连接 并使用以下代码 System Diagnostics Process process2 new System Diagnostics Process System Diagnostics Pr
  • 全局使用和 .NET Standard 2.0

    我最近意识到我可以使用 C 10 功能文件范围的命名空间在 NET Standard 2 0 项目中也可以通过设置
  • 带有运算符语法的错误消息,但不带有函数语法的错误消息

    为什么我在调用 unary 时收到错误消息 使用运算符语法 如果我用函数语法调用它就可以了 现场演示 https godbolt org z j7AbeQ template
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • 静态类与类的实例

    我有一个静态类 用于访问我的公共属性 整个应用程序的全局属性 和我在应用程序运行期间使用的方法 例如 我在静态类中设置了一些属性 并且在应用程序运行时我可以从属性中获取值 但我可以使用单例模式创建非静态类并以相同的方式使用它 问题 对于我的
  • 在 C# 中何时使用 ArrayList 而不是 array[]?

    我经常使用一个ArrayList而不是 正常 array 当我使用时 我感觉好像我在作弊 或懒惰 ArrayList 什么时候可以使用ArrayList在数组上 数组是强类型的 并且可以很好地用作参数 如果您知道集合的长度并且它是固定的 则
  • 子目录中的头文件(例如 gtk/gtk.h 与 gtk-2.0/gtk/gtk.h)

    我正在尝试使用 GTK 构建一个 hello world 其中包括以下行 include
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 如何在 C# 中获取 Json 数组?

    我有一个像这样的 Json 字符串 我想将它加载到 C 数组中 当我尝试这样做时 我收到异常 我的字符串 customerInformation customerId 123 CustomerName Age 39 Gender Male
  • 使用 OleDbCommandBuilder 时访问 SQL 语法错误

    我要在 C 中使用 OleDbDataAdapter 在 Access 数据库中插入数据 但收到错误消息INSERT INTO 命令中的语法错误 BackgroundWorker worker new BackgroundWorker Ol
  • EnumDisplayDevices 与 WMI Win32_DesktopMonitor,如何检测活动监视器?

    对于我当前的 C 项目 我需要为在大量计算机上连接并处于活动状态的每个监视器检测一个唯一的字符串 研究指出了两种选择 使用 WMI 并查询 Win32 DesktopMonitor 以获取所有活动监视器 使用 PNPDeviceID 来唯一
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • 从 NumPy 数组到 Mat 的 C++ 转换 (OpenCV)

    我正在围绕 ArUco 增强现实库 基于 OpenCV 编写一个薄包装器 我试图构建的界面非常简单 Python 将图像传递给 C 代码 C 代码检测标记并将其位置和其他信息作为字典元组返回给 Python 但是 我不知道如何在 Pytho
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • printf或iostream如何指定点后的最大位数

    字符串采用什么格式printf or iomanip我应该使用 iostream 中的运算符以以下格式打印浮点数 125 0 gt 125 125 1 gt 125 1 125 12312 gt 125 12 1 12345 gt 1 12
  • 如果“嵌入式”SQL 2008 数据库文件不存在,如何创建它?

    我使用 C ADO Net 和在 Server Management Studio 中创建的嵌入式 MS SQL 2008 数据库文件 附加到 MS SQL 2008 Express 创建了一个数据库应用程序 有人可以向我指出一个资源 该资
  • 将 char 绑定到枚举类型

    我有一段与此非常相似的代码 class someclass public enum Section START MID END vector section Full void ex for int i 0 i section

随机推荐

  • 哈希学习简介

    一 背景介绍 1 首先介绍一下最近邻搜索 最近邻搜索问题 也叫相似性搜索 近似搜索 是从给定数据库中找到里查询点最近的点集的问题 给定一个点集 以及一个查询点q 需要找到离q最近的点的集合 在大规模高维度空间的情况下 这个问题就变得非常难
  • android 进程监控 top

    adb shell top h top h Usage top m max procs n iterations d delay s sort column t h m num Maximum number of processes to
  • mybatis-plus自定义分页实现 (精)

    添加pom依赖
  • EVE-NG初始安装及配置_笔记

    1 安装VMware 2 导入EVE的ova镜像 3 初始化配置 ubantu server linux 设置root密码 域名 主机名 IP地址 root eve 123456 123456 主机名 域名 IP地址获取 DHCP STAT
  • mysql数据库管理-mysql分区表管理

    1 分区概述 无论是哪种 MySQL 分区类型 要么分区表上没有主键 唯一键 要么分区表的主键 唯一键都必须包含分区键 也就是说不能使用主键 唯一键字段之外的其他字段分区 例如 emp 表的主键为id字段 在尝试通过store id字段分区
  • React实现拖拽效果

    最近遇到一个拖拽的业务 那么我们需要了解一下拖拽的流程 让我们来实现这个组件吧 一 拖拽流程 编写项目之前我们先了解一下拖拽大致的流程 以及触发的事件 其实拖拽一共分为三个步骤 1 onmousedown 拖拽事件的最开始 在这个简单我们要
  • 发现一个xdotool,是个神器

    xdotool是linux下 类似 按键精灵 的工具 在一些自动测试时 经常用到 以上为xdotool正常使用 比如说 模拟击键a xdotool key a 模拟两个键alt tab xdotool key alt Tab 自动输入wor
  • SeaTunnel本地运行以及kafka发送到redis说明

    下载 Seatunnel2 3 1源码 Idea中的目录结构 编译 通过maven进行代码编译 编译命令 mvn clean package pl seatunnel dist am Dmaven test skip true 编译单个模块
  • 【恶意代码与软件安全分析】(三)dynamic analysis

    恶意代码与软件安全分析 三 virtualbox崩掉了 只能跳过第二章先做第三章了 动态分析 在一个安全的环境下运行恶意软件并观察其行为 分析后输出内容 process Service Behavior 进程创建 进程终止 进程数 netw
  • Vue再学习2_组件开发

    Vue再学习2 组件开发 全局组件 在main js中配置 配置完成之后可以全局使用 1 引入组件对象 import GlobalTitle from components GlobalTitle vue 2 声明全局组件 Vue comp
  • cmd 执行html文件,cmd执行bat文件 cmd文件和bat文件有什么区别?

    cmd怎么执行dos下的bat文件在文件目录直接输入bt4 bat就可以了 记住要输入完整的文件名 包换后缀名 比如 11 bat在D盘根目录 在D gt 后面直接输入11 bat 回车 cmd下执行bat文件的命令 在cmd下执行bat文
  • idea 将springboot项目的Application加入service标签里

    idea 将springboot项目的Application启动器加入service标签里 最终效果图如下 第一步 最开始底部显示没有service服务 添加service 第三步 完成以上操作后底部会这样显示 然后点击 第四步 选择Mav
  • SQL Server [使用SSMS来分离数据库] 奋斗的珂珂~

    分离数据库 分离数据库就是将某个数据库 如student Mis 从SQL Server数据库列表中删除 使其不再被SQL Server管理和使用 但该数据库的文件 MDF 和对应的日志文件 LDF 完好无损 分离成功后 我们就可以把该数据
  • Android中的ConstraintLayout约束布局

    ConstraintLayout约束布局 ConstraintLayout有啥好处呢 可以减少布局层次 特别适合复杂的大型布局 可谓是集线性布局和相对布局于一身的荣誉布局 使用 添加依赖 目前 AndroidStudio新的版本默认就给你上
  • MMdetection3D学习系列(二)——KITTI数据集训练测试及可视化

    安装完环境以后 就可以进行测试了 这里我使用的是KITTI数据集进行测试 关于KITTI数据集 网上有很多介绍了 这里简单说一下在mmdet3d中它需要的文件层级样式吧 主要是针对RGB和点云数据进行检测 一般来说采用其中一侧的彩色摄像头的
  • centos7重启或关机卡死

    这个问题其实是systemd219这个版本的问题 查看systemd版本 请使用systemctl version 由于systemd进程的判断比之前更加严格 如果某些进程不响应SIGTERM信号 可能会导致重启是挂死 该问题和业务进程对S
  • Ubuntu查看安装的软件、.开头的文件

    1 dpkg l grep 比如 dpkg l grep libjansson4 2 show hidden files那里
  • Spring整合mybatis和Junit单元测试

    1 Spring整合mybatis 前提了解 spring 管理 mybatis mybatis 管理 mapper 要依赖于德鲁伊连接池 spring 管理sqlsessionfactory 思路 Spring整合Mybatis主要做两件
  • Vue极简使用2

    Vue极简使用 Vue基础内容 模板语法 解析文本 解析原始HTML 动态属性 模板语法使用限制 条件渲染 列表渲染 事件处理 列表渲染 事件处理 修饰符 表单输入绑定 计算属性 样式处理 表单输入和绑定 修饰符 计算属性和监听器 计算属性
  • 差分详细讲解(C++)

    每日一句 平凡的我在人多的地方曾极力小心翼翼 但不知从何时起 我不太在意别人的目光了 比起被人觉得是个怪人 我现在更害怕浪费时间 差分 一 一维差分 二 二维差分 一 一维差分 差分就是前缀和的逆运算 如果你不懂什么是前缀和 看这里 gt