二维前缀和与差分

news/2024/5/18 23:02:32

前言

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

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

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

好吧,开始讲解

二维前缀和

问题描述

有一个二维数组,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.mrgr.cn/p/88345886

相关文章

嵌入式Linux driver开发实操(十八):Linux音频ALSA开发

应用程序程序员应该使用库API,而不是内核API。alsa库提供了内核API 100%的功能,但增加了可用性方面的主要改进,使应用程序代码更简单、更美观。未来的修复程序或兼容性代码可能会放在库代码中,而不是放在内核驱动程序中。 使用ALSA API和libasound进行简单的声音播放: /*…

麒麟 Kylin V10 一键安装 Oracle 11GR2 单机 ASM(231017)

前言 Oracle 一键安装脚本&#xff0c;演示麒麟 Kylin V10 一键安装 Oracle 11GR2 单机 ASM&#xff08;231017&#xff09;过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址&a…

Hbase学习笔记

Hbase是什么 HBase是一个高可靠、高性能、面向列、可伸缩的分布式存储系统。它利用Hadoop HDFS作为其文件存储系统,并提供实时的读写的数据库系统。HBase的设计思想来源于Google的BigTable论文,是Apache的Hadoop项目的子项目。它适合于存储大表数据,并可以达到实时级别。HB…

深度神经网络(DNN)

通过5个条件判定一件事情是否会发生&#xff0c;5个条件对这件事情是否发生的影响力不同&#xff0c;计算每个条件对这件事情发生的影响力多大&#xff0c;写一个深度神经网络&#xff08;DNN&#xff09;模型程序,最后打印5个条件分别的影响力。 示例 在深度神经网络&#xf…

栈(Stack)的原理与代码实现

介绍栈的原理,并分别使用数组和链表实现栈的结构。栈(stack) 原理说明: ​ 学习数据结构的目的是为了更好的处理和存储数据,对于顺序表而言改查比较容易,增删比较麻烦,对于链式表而言,增删比较简单,改查比较麻烦,所以每种数据结构都有不同的特点,用户需要选择合适的…

eBay、亚马逊自养号测评如何避免风控账号关联选择合适网络IP环境

在自养号下单中选择适合的网络环境至关重要。经过多次实践与测试&#xff0c;积累了大量的经验&#xff0c;希望能够与大家分享&#xff0c;帮助大家避开陷阱&#xff0c;顺利前行。 市面上的网络环境种类繁多&#xff0c;从纯IP类的Luminati、Rola&#xff0c;到纯环境类的VM…

linux centos8 系统扩容 VMware Centos---VMware ESXi

linux 系统扩容 VMware Centos---VMware ESXi 用到的命令 df fdisk pvcreate pvdisplay vgdisplay vgextend lvdisplay lvextend resize2fs 01) 使用了一段时间虚拟机后发现磁盘不够用了,需要扩容。在客户端操作扩容出现磁盘已成功扩展。 您必须从客户机操作系…

使用 Redis 实现限流——滑动窗口算法

用 Go 语言实现滑动窗口限流算法,并利用 Redis 作为存储后端,可以按照以下步骤进行设计和编码。滑动窗口限流的核心思想是维护一个固定时间窗口,并在窗口内记录请求次数,当窗口滑动时,旧的请求计数被移除,新的请求计数被添加。这里以 Redis 的有序集合(Sorted Set,简称…

Tomcat调优总结(Tomcat自身优化、Linux内核优化、JVM优化)【转】

Tomcat自身的调优是针对conf/server.xml中的几个参数的调优设置。首先是对这几个参数的含义要有深刻而清楚的理解。以tomcat8.5为例,讲解参数。 同时也得认识到一点,tomcat调优也受制于linux内核。linux内核对tcp连接也有几个参数可以调优。 因此我们可以将tomcat调优分为lin…

提升工作效率必备,桌面待办事项提醒软件

在快节奏的现代社会,提升工作效率成为众多上班族的共同追求。有效的时间管理、合理的工作计划和正确的工具选择,是实现高效工作的三大关键。尤其是选择一款优秀的待办事项管理软件,能够极大地助力我们提升工作效率。 而我在网上找到了一款提升工作效率必备神器软件,它就是2…

S3-FIFO

S3-FIFO 本文作为下一篇缓存文章的预备知识。 背景 基于LRU和FIFO的驱逐 FIFO和LRU都是经典的缓存驱逐算法,在过去几十年中也出现了很多追求更高效率的驱逐算法,如ARC, 2Q, LIRS, TinyLFU。传统观点认为,基于LRU的缓冲未命中率要低于基于FIFO的算法,如CLOCK,这类高级算法通…

python读取yaml配置文件的方法

yaml简介1.yaml [ˈjməl]: Yet Another Markup Language :另一种标记语言。yaml 是专门用来写配置文件的语言,非常简洁和强大,之前用ini也能写配置文件,看了yaml后,发现这个更直观,更方便,有点类似于json格式 2.yaml基本语法规则: 大小写敏感 使用缩进表示层级关系 缩进…

kali /mac 成功的反弹shell语句

mac &#xff1a;192.168.19.107 kali:192.168.19.111 kali 监听mac : nc -lvvp 6666 mac执行&#xff1a; 1: mknod backpipe p && nc 192.168.19.111 6666 0<backpipe | /bin/bash 1>backpipe 2: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&…

信号量(Semaphores)

信号量与pv操作信号量信号量(Semaphore)是一种比互斥锁更强大的同步工具,它可以提供更加高级的方法来同步并发进程。 A semaphore S is an integer variable that ,apart from initialization(初始化),is accessed only through two standard atomic operations:P VP:wait() …

对象和类

private关键字 构造方法 this关键字 局部变量: 方法体中的变量 成员变量: 类中定义的变量(属性) 输出时采用就近原则:即距离输出语句近的 想让他使用属性中同名的变量加上this关键字

nginx 配置 SSL 证书实现 https 访问

nginx 配置SSL证书实现https访问 1. SSL 证书简介与获取1.1 SSL 证书介绍1.2 获取 SSL 证书 2. nginx 配置 SSL 文件2.1 SSL 文件放置与配置文件修改2.1.1 文件配置2.1.2 强制 https 访问 2.2 验证配置结果 同步发布在个人笔记 nginx 配置 SSL 证书实现 https 访问 配置好 ngi…

GaussDB数据库SQL系列-聚合函数

背景 在这篇文章中&#xff0c;我们将深入探讨GaussDB数据库中聚合函数的使用和优化。聚合函数是数据库查询中非常重要的工具&#xff0c;它们可以对一组值执行计算并返回单个值。例如&#xff0c;聚合函数可以用来计算平均值、总和、最大值和最小值。 这些功能在数据分析和报…

Python 彩色字体输出

使用ANSI转译码给print添加颜色 公式 \033[显示方式;字体颜色;背景色m输出内容\033[0m公式参数解析\033 : ANSI转义序列开始标识 [ :控制码 用于控制字体方式、颜色、背景色(控制码对应参数值是唯一的 所以仅设置一个参数时 其他参数可以省略 不用空占用) m :控制…

数据库管理-第176期 浅析代码团队建设(20240425)

数据库管理176期 2024-04-25 数据库管理-第176期 浅析代码团队建设&#xff08;20240425&#xff09;1 国内现状2 需求管控3 竞争与迭代总结 数据库管理-第176期 浅析代码团队建设&#xff08;20240425&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09…

大数据真题讲解系列——拼多多数据分析面试题

拼多多数据分析面试题&#xff1a;连续3次为球队得分的球员名单 问题&#xff1a; 两支篮球队进行了激烈的比赛&#xff0c;比分交替上升。比赛结束后&#xff0c;你有一个两队分数的明细表&#xff08;名称为“分数表”&#xff09;。表中记录了球队、球员号码、球员姓名、得…