二维前缀和与差分

前言

延续前面所讲的一维前缀和以及差分,现在来写写二维前缀和与差分

主要这个画图就比前面的一维前缀和与差分复杂一点,不过大体思路是一样的

一维和二维的主要思路在于一维是只针对对一行一列,而二维是针对与一个矩阵的

好吧,开始讲解

二维前缀和

问题描述

有一个二维数组,int arr[i][j]中从{x1,y1}->{x2,y2}的范围内求和

这里的范围是一个矩形而不是一个路径

举例 ,比如 下面对于一个三行五列的二维数组 求{1,1}->{2,2}的和就是求红色部分的和

1 1 1 1 1

1 1 1 1 1

1 1 1 1 1

暴力思路

那就是根据下表依次相加复杂度为o((x2-x1)*(y2-y1))

其实就是行乘列,这里的暴力代码实在是太简单了,但是不能太懒,还是给大家敲

#define col 5
#define line 3
int main()
{int arr[line][col] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};printf("请输入4个数表示两个坐标\n");int x1, y1, x2, y2;int sum = 0;scanf("%d %d %d %d", &x1,&y1,&x2,&y2);for (int i = x1; i<= x2; i++)for (int j = y1; j<= y2; j++)sum += arr[i][j];printf("%d", sum);return 0;
}

这里的时间复杂度是平方级别的

二维前缀和的思路

1.二维前缀数组的构建

这玩意用文字讲,费时间呢,还是画图来讲解吧

我们这里先把它的代码给出

void pre_sum(int arr[][col])
{sum[0][0] = arr[0][0];for (int i = 1; i < col; i++)sum[0][i] = sum[0][i - 1] + arr[0][i];for (int j = 1; j < line;j++)sum[j][0] = sum[j - 1][0] + arr[j][0];for (int i = 1; i < line; i++){for (int j = 1; j < col; j++){sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1]+arr[i][j];}}
}

2前缀和数组的使用

还是看图吧

OK

我们来看代码吧

//二维前缀和
#define line 3
#define col 5
int sum[line][col];
void pre_sum(int arr[][col])
{sum[0][0] = arr[0][0];for (int i = 1; i < col; i++)sum[0][i] = sum[0][i - 1] + arr[0][i];for (int j = 1; j < line;j++)sum[j][0] = sum[j - 1][0] + arr[j][0];for (int i = 1; i < line; i++){for (int j = 1; j < col; j++){sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1]+arr[i][j];}}
}
int result(int x1, int y1, int x2, int y2)
{if (x1 == 0 && y1 == 0)return sum[x2][y2];else if (x1 == 0)return sum[x2][y2] - sum[x2][y1 - 1];else if (y1 == 0)return sum[x2][y2] - sum[x1 - 1][y2];else return sum[x2][y2] - sum[x2][y1-1] - sum[x1-1][y2] + sum[x1 - 1][y1 - 1];
}
int main()
{int arr[line][col] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11,12,13,14,15}};pre_sum(arr);printf("%d", result(1, 0, 2, 2));
}

那么接下来看差分了

二维差分

理解了二为前缀和,那么二维差分就很简单了,同样也是一个矩阵作为作用的对象

问题描述

有一个二维数组,int arr[i][j]中从{x1,y1}->{x2,y2}的范围内求和

这里的范围是一个矩形而不是一个路径

举例 ,比如 下面对于一个三行五列的二维数组 求{1,1}->{2,2}对他们加上某个数

假设这个数为1

1 1 1 1 1       那么结果是 1 1 1 1 1

1 1 1 1 1                          1 2 2 1 1 

1 1 1 1 1                          1 2 2 1 1

暴力思路

其实真的有点不想写了,哎呦!!!!!!

还是再来吧!!!!!!

看代码

#define col 5
#define line 3
int main()
{int arr[line][col] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};printf("请输入4个数表示两个坐标\n");int x1, y1, x2, y2,val;scanf("%d %d %d %d", &x1,&y1,&x2,&y2);printf("再输入一个数作为操作数");scanf("%d",&val);for (int i = x1; i<= x2; i++)for (int j = y1; j<= y2; j++)arr[i][j]+=val;printf("%d", sum);return 0;
}

差分思路

其实这里用不到差分数组,只是把一个比原来二维数组行列都大1的一个数组全部初始化为0

然后,作为一个影响,去进行前缀和,把产生的影响加到原有的数组中

看图吧

思路上与前缀和差不多,我们主要讲如何使用

假设有两个坐标(x1,y1),(x2,y2)

构建一个二维数组,元素全部为0  d[line+1][col+1];

其实核心的代码为

d[x1][y1] += value;产生影响
d[x2 + 1][y1] -= value;让后面的元素不受影响
d[x1][y2 + 1] -= value;让后面的元素不受影响
d[x2 + 1][y2 + 1] += value;让后面的元素不受影响,多减去了

看图

看代码呗

#define line 3
#define col 5
int d[line + 1][col + 1] = {0};
void pre_d(int arr[][col])
{for (int i = 1; i <=col; i++)d[0][i]+=d[0][i-1];for (int j = 1; j <=line;j++)d[j][0]+=d[j-1][0];for (int i = 1; i <=line; i++){for (int j = 1; j <=col; j++){d[i][j]+=d[i][j-1]+d[i-1][j]-d[i-1][j-1];}}for (int i = 0; i < line; i++){for (int j = 0; j < col; j++){arr[i][j] += d[i][j];}}
}
void fun(int x1, int y1, int x2, int y2,int value)
{d[x1][y1] += value;d[x2 + 1][y1] -= value;d[x1][y2 + 1] -= value;d[x2 + 1][y2 + 1] += value;
}
void printf_a(int arr[][col])
{for (int i =0; i < line; i++){for (int j = 0; j < col; j++)printf("%d ", arr[i][j]);printf("\n");}
}
void printf_d()
{for (int i = 0; i <=line; i++){for (int j = 0; j<=col;j++)printf("%d ", d[i][j]);printf("\n");}
}
int main()
{int arr[line][col] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11,12,13,14,15}};fun(0, 0, 2, 1,-1);fun(0, 2, 2, 4, 5);pre_d(arr);printf("\n");printf_a(arr);
}

总结

最后,如果大家感兴趣的话可以试试三维数组

好吧,就这样吧,睡个好觉,祝大家开心啊!

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

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

相关文章

flutter组件 ThemeData

这里只讲组件的定义&#xff0c;需要各位自己去尝试。 ThemeData({// 常规配置Iterable<Adaptation<Object>>? adaptations, // 定义主题自适应方案的列表。bool? applyElevationOverlayColor, // 是否应用海拔叠加颜色。NoDefaultCupertinoThemeData? cuperti…

从零开始精通RTSP之深入理解RTP协议

概述 RTP&#xff0c;即实时传输协议&#xff0c;英文全称为Real-Time Transport Protocol&#xff0c;是一种用于在互联网上传输视频、音频等实时数据的网络协议。RTP本身不提供任何服务质量保证&#xff0c;而是依赖于底层传输协议&#xff08;比如&#xff1a;UDP&#xff0…

ACE框架学习2

目录 ACE Service Configurator框架 ACE_Server_Object类 ACE_Server_Repository类 ACE_Server_Config类 ACE Task框架 ACE_Message_Queue类 ACE_TASK类 在开始之前&#xff0c;首先介绍一下模板类的实例化和使用。给出以下代码 //ACCEPTOR代表模板的方法 template <…

VSCode插件开发学习

一、环境准备 0、参考文档&#xff1a;VS Code插件创作中文开发文档 1、大于18版本的nodejs 2、安装Yeoman和VS Code Extension Generator&#xff1a; npm install -g yo generator-code 3、生成脚手架 yo code 选择内容&#xff1a; ? What type of extension do yo…

DASCTF X GFCTF 2024|四月开启第一局

前言 题目都比较简单&#xff0c;&#xff0c;&#xff0c;没啥好说的&#xff0c;很久没做题了&#xff0c;简单记录一下 dynamic_but_static 仅仅开了 NX 保护栈溢出 先泄漏 libc 地址&#xff0c;然后栈溢出打 ret2libc&#xff0c;开了沙箱得 orw from pwn import * c…

Vue3+TS版本Uniapp:项目前置操作

作者&#xff1a;前端小王hs 阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主 环境&#xff1a;使用vscode进行开发 如果一开始是使用的HbuilderX&#xff0c;请看hbuilderX创建的uniapp项目转移到vscode 为什么选择vscode&#xff1f;有更好…

Docker容器的原理及应用详解(三)

本系列文章简介&#xff1a; Docker是一种开源的容器化技术&#xff0c;它将应用程序及其依赖项打包为一个容器&#xff0c;以便在任何环境下运行。与传统的虚拟机相比&#xff0c;Docker容器更加轻量级且快速&#xff0c;可以在几秒钟内启动和停止。Docker的原理和应用非常广泛…

Windows进入黑屏,操作CMD提示命令提示符已被系统管理员停用

背景 由于安装或者卸载某些服务导致主机无法正常显示桌面&#xff0c;从控制台进入打开操作执行命令提示禁用。 操作步骤 注意务必做好快照备份后再操作。 打开注册表中将其重新启用&#xff1a; 依次打开“运行”命令&#xff0c;然后在打开的“运行”对话框中输入 “regedit…

一个简单的记工tkinter窗口

代码分享: 导入datetime模块&#xff0c;用于获取当前日期 import datetime as da 导入csv模块&#xff0c;用于读写csv文件 import csv 导入tkinter模块&#xff0c;用于创建窗口和按钮 from tkinter import * 创建主窗口 appTk() 设置窗口大小为1048x2048&#xff0…

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第六套

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第六套 (共9套&#xff0c;有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09; 部分题目分享&#xff0c;完整版获取&#xff08;WX:didadidadidida313&#xff0c;加我备注&#x…

【OpenHarmony-NDK技术】简单将cJson移植到OpenHarmony中,并在c层修改参数值再返回json

1、cJson的简单介绍 cJson - github网址 概述 一般使用cJson是&#xff0c;需要将json文本转化为json对象–编码&#xff0c;将json对象转化为json文本–解析。 git clone https://github.com/DaveGamble/cJSON.git 后留意cJSON.h和cJSON.h两个文件。 1、cJson的介绍 cJso…

【Kafka】KafkaTopic命令

【Kafka】KafkaTopic命令 1. topic命令 1. topic命令 查看集群中所有的topic [roothcss-ecs-2ff4 kafka]# kafka-topics.sh --bootstrap-server 101.42.49.137:9092,139.9.133.30:9092,114.116.254.124:9092 --list# 创建一个topic 一个节点创建其他节点也有 [rootVM-8-7-cen…

Golang那些违背直觉的编程陷阱

目录 知识点1&#xff1a;切片拷贝之后都是同一个元素 知识点2&#xff1a;方法集合决定接口实现&#xff0c;类型方法集合是接口方法集合的超集则认定为实现接口&#xff0c;否则未实现接口 切片拷贝之后都是同一个元素 package mainimport ("encoding/json"&quo…

深入解读:BIO、NIO与IO多路复用——理解现代网络编程基石

在现代软件开发中&#xff0c;高效的数据交换是构建高性能网络应用的核心要素。深入理解输入输出&#xff08;Input/Output,简称IO&#xff09;模型的底层原理与工作机制&#xff0c;对于设计和实现高并发、低延迟的网络服务至关重要。本文将深度剖析阻塞式I/O&#xff08;BIO&…

k8s和docker的一些学习(一)

https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html //dockerfile总结&#xff08;TO READ&#xff09; 不太懂的就是VOLUME的概念&#xff08;数据卷&#xff09;&#xff0c;问了一下GPT Q:docker的VOLUME是什么作用&#xff1f;详细解答一下 A:在 Docker 中&#x…

Redis 如何实现分布式锁

课程地址 单机 Redis naive 版 加锁&#xff1a; SETNX ${lockName} ${value} # set if not exist如果不存在则插入成功&#xff0c;返回 1&#xff0c;加锁成功&#xff1b;否则返回 0&#xff0c;加锁失败 解锁&#xff1a; DEL ${lockName}问题1 2 个线程 A、B&#…

前后端交互概念

前后端交互概念 1前后端分离开发概念2搭建后端环境2.1配置文件commomcommon-utilservice-utilmodelservice gitee使用 1前后端分离开发概念 前段&#xff1a;运用html、css、js和现成库&#xff0c;对数据作展示。 后端&#xff1a;运用Java和Java框架&#xff0c;提供数据或操…

立创·实战派ESP32-C3开发板 with lv_micropython

一、lv_micropython对驱动芯片的支持 ESP32-C3开发板的Display drivers:ST7789&#xff0c;Input drivers:FT6336&#xff0c;从LVGL的官方文档了解到lv_micropython包含了这两颗IC的驱动。 参考文档&#xff1a; lv_micropython already contains these drivers: 链接:Micro…

智慧化转型赋能园区创新:科技创新引领产业智慧化,打造高效发展新格局

在全球化和信息化浪潮的推动下&#xff0c;园区作为区域经济发展的重要引擎&#xff0c;正面临着前所未有的机遇与挑战。为应对这些挑战并把握机遇&#xff0c;园区需积极拥抱智慧化转型&#xff0c;通过科技创新引领产业智慧化&#xff0c;打造高效发展的新格局。本文将深入探…

贝叶斯分类 python

贝叶斯分类 python 贝叶斯分类器是一种基于贝叶斯定理的分类方法&#xff0c;常用于文本分类、垃圾邮件过滤等领域。 在Python中&#xff0c;我们可以使用scikit-learn库来实现贝叶斯分类器。 下面是一个使用Gaussian Naive Bayes(高斯朴素贝叶斯)分类器的简单示例&#xff1…