二维前缀和与差分

news2024/9/29 7:25:46

前言

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

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

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

好吧,开始讲解

二维前缀和

问题描述

有一个二维数组,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.coloradmin.cn/o/1614731.html

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

相关文章

可视化大屏在政务领域应用非常普遍,带你看看

可视化大屏在政务领域的应用非常普遍&#xff0c;政务领域需要处理大量的数据和信息&#xff0c;通过可视化大屏可以将这些数据以直观、易懂的方式展示出来&#xff0c;帮助政府决策者和工作人员更好地了解和分析数据&#xff0c;从而做出更准确、科学的决策。 在政务领域&…

java学习之路-抽象类和接口

目录 前言 1.抽象类 1.2抽象类语法 1.3抽象类特性 1.4抽象类的作用 2.接口 2.1接口概念 2.2接口的定义 2.3接口的使用 接口使用栗子 2.4接口特性 2.5 实现多个接口 请看栗子 2.6接口间的继承 2.7接口使用实例 2.8Clonable 接口和深浅拷贝 2.9 抽象类和接口的区别…

Qt图片等资源管理

Qt的图片等资源管理通常有两种方式 1&#xff0c;直接将图标和一些配置文件打包在可执行程序中 添加qrc文件&#xff0c;可使用qtcreator直接添加 右键选中工程 点击选择即可。 然后添加文件。我这个例子是添加了Image文件夹下的图片资源 使用的时候&#xff0c;可以在代码…

MySQL学习笔记1(MySQL基础)

1.MySQL基础 1.数据库相关概念 ​ *数据库&#xff1a;存储数据的仓库&#xff0c;数据是有组织的进行存储 DtaBase(DB) ​ *数据管理系统&#xff1a;操纵和管理数据库的大型软件 DataBase Management System (DBMS) ​ *SQL&#xff1a;操作关系型数据库的编程语言&#…

【GNSS】GNSS开源相关代码汇总

仅作为笔者的学习笔记使用 参考&#xff1a;GNSS算法相关开源代码&#xff08;含多传感器融合相关项目&#xff09; - 知乎 (zhihu.com)

C语言本身不难,难得是应用场景很多

你学了C语言多半是要做项目的&#xff0c;这个过程中C语言是远远不够的&#xff0c;你把这部分难度加到C语言上&#xff0c;自然就难了在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区…

浅谈防火墙,IPS,APT威胁检测的互补性

在学习网络安全产品时发现很多产品的目的与功能大同小异都是防范非法流量或威胁&#xff0c;但是既然有产品的差异就有作用的目的的差异&#xff0c;下面浅谈一下三个网络安全产品的差异化与互补点 防火墙 传统防火墙主要是工作在二到四层&#xff0c;不会对报文的载荷进行检…

大家期待的「红米汽车」,可能真的要来了

不知道从啥时候开始&#xff0c;小米逐渐摘掉了那顶让人越看越顺眼的「亲民帽子」。 从最开始 1999 到后来 3999 甚至是 4999、5999&#xff0c;雷军口中的高端梦正在一步步实现。 前段时间小米首款汽车 SU7 上市&#xff0c;21.59-29.99 万元定价再次引来大批网友直呼&#…

串联滞后校正及matlab实现

syms b_1 Z[]; P[0,-10,-5]; K1500; G_0zpk(Z,P,K); %G_0为校正前系统开环传递函数 [num,den]tfdata(G_0); %求解b&#xff0c;T [Gm,Pm,wg_0,wc_0]margin(G_0); %Pm为校正前的幅值裕度, gamma60; %确定校正后的相角裕度 Phi_c-6; %校正后的截止频率下Gc(s)的相角&#xff0c;一…

C++ 散列表(hash table)

目录 一&#xff0c;哈希表 1&#xff0c;哈希表概述 2&#xff0c;哈希函数 3&#xff0c;碰撞冲突 二&#xff0c;代码实现 1&#xff0c;哈希函数与素数函数 2&#xff0c;哈希节点与哈希表数据结构 3&#xff0c;构造、析构以及一些简单的功能 4&#xff0c;清空&…

如何使用渐变块创建自定义聊天机器人

如何使用渐变块创建自定义聊天机器人 文章目录 如何使用渐变块创建自定义聊天机器人一、介绍二、参考示例1、一个简单的聊天机器人演示2、将流式传输添加到您的聊天机器人3、喜欢/不喜欢聊天消息4、添加 Markdown、图像、音频或视频 一、介绍 **重要提示&#xff1a;**如果您刚…

《你想活出怎样的人生》上映,AOC带你打开宫崎骏的动画世界大门!

摘要&#xff1a;宫崎骏式美学&#xff0c;每一帧都是治愈&#xff01; 近日&#xff0c;宫崎骏新作《你想活出怎样的人生》正式公映。苍鹭与少年的冒险、奇幻瑰丽的场景、爱与成长的主题&#xff0c;让观众们收获到满满的爱与感动。宫崎骏总能以细腻的画面、温柔的音乐&#…

LeetCode - 面试题 08.06. 汉诺塔问题

目录 题目链接 解题思路 解题代码 题目链接 LeetCode - 面试题 08.06. 汉诺塔问题 解题思路 假设 n 1,只有一个盘子&#xff0c;很简单&#xff0c;直接把它从 A 中拿出来&#xff0c;移到 C 上&#xff1b; 如果 n 2 呢&#xff1f;这时候我们就要借助 B 了&#xff0c;因…

select实现echo服务器的并发

select实现echo服务器的并发 代码实现 #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <arpa/inet.h> #include <sys/select.h> #include <sys/time.h…

14. Spring AOP(二)实现原理

源码位置&#xff1a;spring_aop 上一篇文章中我们主要学习了AOP的思想和Spring AOP使用&#xff0c;本文讲的是Spring是如何实现AOP的&#xff0c;Spring AOP是基于动态代理来实现AOP的&#xff0c;在将动态代理之前先来了解一下什么是代理模式。 1. 代理模式 在现实中就有许…

【算法刷题 | 回溯思想 07】4.18(全排列、全排列 ||)

文章目录 11.全排列11.1题目11.2解法&#xff1a;回溯11.2.1回溯思路&#xff08;1&#xff09;函数返回值以及参数&#xff08;2&#xff09;函数返回值&#xff08;3&#xff09;遍历过程 11.2.2代码实现 12.全排列 ||12.1题目12.2解法&#xff1a;回溯12.2.1回溯思路12.2.3代…

教师编制可以跨市调动吗

在教育的广阔天地中&#xff0c;我们常常面临各种职业发展的选择。作为一名教师&#xff0c;是否能够实现跨市调动&#xff0c;这不仅是一个职业发展的问题&#xff0c;更关系到个人生活和职业规划的诸多方面。今天&#xff0c;我们就来探讨一下&#xff0c;拥有编制身份的教师…

2024免费专为Mac用户设计的清理和优化工具CleanMyMac X

CleanMyMac X是一款专为Mac用户设计的清理和优化工具。以下是对CleanMyMac X的详细介绍&#xff1a; 一、主要功能 系统清理&#xff1a;CleanMyMac X能够智能扫描Mac的磁盘空间&#xff0c;识别并清理各种垃圾文件&#xff0c;这些垃圾文件包括重复文件、无用的语言安装包、i…

模拟信号的离散化

本文介绍模拟信号的离散化。 1.采样定理 定义&#xff1a;若想重建输入的模拟信号&#xff0c;采样频率必须大于等于输入模拟信号最高频率的2倍&#xff0c;即&#xff1a; 其中&#xff0c;为采样频率&#xff0c;为输入模拟信号最高频率 否则&#xff0c;信号会发生混叠 2…

攻防世界---misc---easycap

1.下载附件是一个流量包&#xff0c;拿到wireshark中分析 2.查看分级协议 3.过滤data 4.追踪tcp流 5.得到flag