【CSP考点回顾】二维前缀和数组(代码实现)

1. 初始化扩展的二维前缀和数组

创建一个大小为 (rows + 1) x (cols + 1) 的二维前缀和数组,其中 rowscols 分别是原始数组的行数和列数。然后,我们按以下方式填充这个数组:

void initPrefixSum(vector<vector<int>>& prefixSum, const vector<vector<int>>& matrix) {int rows = matrix.size();int cols = matrix[0].size();// 初始化扩展了的前缀和数组prefixSum.resize(rows + 1, vector<int>(cols + 1, 0));for (int i = 1; i <= rows; ++i) {for (int j = 1; j <= cols; ++j) {prefixSum[i][j] = matrix[i - 1][j - 1]+ prefixSum[i - 1][j]+ prefixSum[i][j - 1]- prefixSum[i - 1][j - 1];}}
}

2. 查询扩展的二维前缀和数组

由于我们的前缀和数组是扩展过的,因此查询时的坐标也需要相应地调整。例如,如果我们要查询原始数组中从 (x1, y1)(x2, y2) 的子矩阵的和,我们可以使用以下代码进行查询:

int queryPrefixSum(const vector<vector<int>>& prefixSum, int x1, int y1, int x2, int y2) {// 调整索引,因为前缀和数组是扩展了的int sum = prefixSum[x2 + 1][y2 + 1]- prefixSum[x1][y2 + 1]- prefixSum[x2 + 1][y1]+ prefixSum[x1][y1];return sum;
}

注意,在查询时,我们需要对原始数组的索引进行加1处理,因为我们的前缀和数组的起始索引是从1开始的,而非0。这种方式简化了边界检查的需求,因为所有的从原点到(x, y)的查询都可以直接使用上面的公式,不再需要特别处理边界情况。

3.二维前缀和数组还原原始数组

前缀和数组是通过累加原始数组中的元素构建的,因此还原原始数组实质上是一个逆累加(或逆差分)的过程。下面是一个实现这一过程的C++函数示例。前缀和数组大小为 (rows + 1) x (cols + 1),并且我们希望从这个扩展的前缀和数组还原出原始的大小为 rows x cols 的数组:

vector<vector<int>> restoreOriginalArray(const vector<vector<int>>& prefixSum) {int rows = prefixSum.size() - 1;  // 原始数组的行数int cols = prefixSum[0].size() - 1;  // 原始数组的列数vector<vector<int>> originalArray(rows, vector<int>(cols, 0));for (int i = 1; i <= rows; ++i) {for (int j = 1; j <= cols; ++j) {// 还原原始数组的值originalArray[i - 1][j - 1] = prefixSum[i][j]- prefixSum[i - 1][j]- prefixSum[i][j - 1]+ prefixSum[i - 1][j - 1];}}return originalArray;
}

在这个函数中,我们遍历扩展后的前缀和数组,使用类似于查询前缀和的反向过程来计算原始数组的每个元素。每个元素的值是由当前位置的前缀和减去其上方和左侧的前缀和,再加上其左上角(即前一个)的前缀和得到的。这正好是构建前缀和时使用的逆过程。这个函数返回的 originalArray 就是还原后的原始二维数组。

4.完整代码(附测试样例)

#include <iostream>
#include <vector>using namespace std;// 初始化扩展的二维前缀和数组
void initPrefixSum(vector<vector<int>>& prefixSum, const vector<vector<int>>& matrix) {int rows = matrix.size();int cols = matrix[0].size();prefixSum.resize(rows + 1, vector<int>(cols + 1, 0));for (int i = 1; i <= rows; ++i) {for (int j = 1; j <= cols; ++j) {prefixSum[i][j] = matrix[i - 1][j - 1]+ prefixSum[i - 1][j]+ prefixSum[i][j - 1]- prefixSum[i - 1][j - 1];}}
}// 查询扩展的二维前缀和数组中子矩阵的和
int queryPrefixSum(const vector<vector<int>>& prefixSum, int x1, int y1, int x2, int y2) {int sum = prefixSum[x2 + 1][y2 + 1]- prefixSum[x1][y2 + 1]- prefixSum[x2 + 1][y1]+ prefixSum[x1][y1];return sum;
}// 从扩展的二维前缀和数组还原原始数组
vector<vector<int>> restoreOriginalArray(const vector<vector<int>>& prefixSum) {int rows = prefixSum.size() - 1;int cols = prefixSum[0].size() - 1;vector<vector<int>> originalArray(rows, vector<int>(cols, 0));for (int i = 1; i <= rows; ++i) {for (int j = 1; j <= cols; ++j) {originalArray[i - 1][j - 1] = prefixSum[i][j]- prefixSum[i - 1][j]- prefixSum[i][j - 1]+ prefixSum[i - 1][j - 1];}}return originalArray;
}int main() {vector<vector<int>> matrix = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};vector<vector<int>> prefixSum;initPrefixSum(prefixSum, matrix);cout << "Prefix Sum Array:" << endl;for (const auto& row : prefixSum) {for (int val : row) {cout << val << " ";}cout << endl;}int sum = queryPrefixSum(prefixSum, 1, 1, 2, 2); // 查询从(1, 1)到(2, 2)的子矩阵的和cout << "Queried sum: " << sum << endl;vector<vector<int>> restoredArray = restoreOriginalArray(prefixSum);cout << "Restored Original Array:" << endl;for (const auto& row : restoredArray) {for (int val : row) {cout << val << " ";}cout << endl;}return 0;
}

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

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

相关文章

自动驾驶的几种名词

1. 自适应巡航控制&#xff08;ACC&#xff09; 自适应巡航控制&#xff08;Adaptive Cruise Control&#xff0c;ACC&#xff09;是一种汽车驾驶辅助系统&#xff0c;它可以根据前方车辆的速度和距离自动调整车辆的速度&#xff0c;以保持与前车的安全距离。ACC系统由控制层和…

使用ChatGPT的场景之gpt写研究报告,如何ChatGPT写研究报告

推荐写研究报告使用智能站&#xff1a; dayfire.cn/ 1. 确定研究主题 明确主题&#xff1a;在开始之前&#xff0c;你需要有一个清晰的研究主题。这将帮助AI更好地理解你的需求…

上位机图像处理和嵌入式模块部署(qmacvisual拟合圆和拟合椭圆)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们学习了拟合直线&#xff0c;今天继续学习下拟合圆和拟合椭圆。其实除了最后一步不同&#xff0c;两者的逻辑是差不多的。一般都是&#xf…

elasticsearch+kibana安装部分问题:

1.elasticsearch启动问题&#xff1a; 如果elasticsearch开启https登录则第一次启动的时候需要前台启动&#xff0c;前台启动的时候会自己创建相应的token等登录信息,如果是后台启动则没有这些登录信息&#xff1a; ./elasticsearch ━━━━━━━━━━━━━━━━━━━…

SQL简单查询-2

目录 第一关任务描述 相关知识 检索数据表中一个字段的内容 检索数据表中多个字段的内容 检索数据表中所有字段的内容 编程要求 测试说明 第一关实验代码&#xff1a; 第二关任务描述 相关知识 带限制条件的查询 表达式查询 编程要求 第二关实验代码 第三关任务描…

【电机-电机控制】

电机-电机控制 ■ 步进电机■ 简介 ■■ ■ 步进电机 ■ 简介 步进电机是一个把电脉冲信号转换为角位移或线位移动的电动机。 ■ ■

(delphi11最新学习资料) Object Pascal 学习笔记---第7章第5节(完整的TDate类)

7.5.3 完整的TDate类 ​ 在本章中&#xff0c;我向您展示了TDate类不同版本的源代码的片段。第一个版本基于三个整数来存储年份、月份和日期&#xff1b;第二个版本使用RTL提供的TDateTime类型的字段。以下是定义TDate类的单元的完整接口部分&#xff1a; unit Dates; interf…

零基础入门多媒体音频(5)-alsa(1)

alsa是音频最重要的框架&#xff0c;没有之一。接下来一个月时间在总结工作知识的主线上。单开个音频支线讲解alsa。说实话&#xff0c;alsa这块我也不是很精通。只在过去的项目中增加 一路substream实现低延时。我打算从下面四个方面去学习alsa。 1.alsa官网。网址如下&#x…

汉明校验·简明教程

汉明校验 一、简介 汉明码是由 Richard Hanming 于 1950 年提出的&#xff0c;它具有一位纠错能力。 新增的汉明码校验位数应满足如下关系&#xff1a; 2 k ⩾ n k 1 2^{k}\geqslant nk1 2k⩾nk1&#xff0c;其中k为校验位位数&#xff0c;n位数据位数。 二、汉明码生成 确…

Python学习从0到1 day18 Python可视化基础综合案例 3.动态柱状图

夜色难免黑凉&#xff0c;前行必有曙光。 —— 24.3.25 目录&#xff1a; 01.基础柱状图 02.基础时间线柱状图 03.GDP动态柱状图绘制 一、基础柱状图构建 掌握构建一个基础的柱状图并能够反转x和y轴 1.通过Bar功能构建基础柱状图 基础柱状图的开发 # 导包 Bar包&#xff0c;生…

吴恩达2022机器学习专项课程(一) 第一周课程实验:成本函数(Lab_04)

问题预览 1.实验目的是什么&#xff1f; 2.一元线性回归的一元是什么意思&#xff1f; 3.如何实现一元线性回归的成本函数&#xff1f; 4.b确定&#xff0c;w和成本函数走势的关系是&#xff1f; 5.w&#xff0c;b和等高线图的关系是&#xff1f; 6.什么情况下&#xff0c;可以…

linux查看本机开放哪些端口,以及某个端口是否开放

一、查看Linux系统上已经打开的端口 netstat -tuln二、查看某个端口是否开放 以3306端口为例&#xff1a; 1、nestat sudo netstat -tuln | grep 3306这条命令将列出当前正在运行的网络服务&#xff0c;并筛选出端口号为3306的服务。如果3306端口处于开放状态&#xff0c;则…

反相器的工艺结构原理及选型参数总结

🏡《总目录》 目录 1,概述2,工作原理3,结构特点3.1,输入与输出电平相反3.2,增益小于13.3,输入阻抗高,输出阻抗低4,工艺流程4.1,硅晶圆准备4.2,电路设计4.3,光刻图形定义4.4,离子注入4.5,沉积4.6

javaWeb个人日记(博客)管理系统

一、简介 在快节奏的生活中&#xff0c;记录生活点滴、感悟和思考是一种重要的方式。基于此&#xff0c;我设计了一个基于JavaWeb的个人日记本系统&#xff0c;旨在帮助用户轻松记录并管理自己的日记。该系统包括登录、首页、日记列表、写日记、日记分类管理和个人中心等功能&…

动态多态的注意事项

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答。 多态的基本概念 多态是C面向对象三大特性之一&#xff08;多态、继承、封装&#xff09; 多态分为两类&#xff1a; 静态多态&#xff1a;函数重载和运算符重载属于静态多态&#x…

深入了解 Linux 中的 MTD 设备:/dev/mtd* 与 /dev/mtdblock*

目录 前言一、什么是MTD子系统&#xff1f;二、 /dev/mtd* 设备文件用途注意事项 三、/dev/mtdblock* 设备文件用途注意事项 三、这两种设备文件的关系四、关norflash的一些小知识 前言 在嵌入式Linux系统的世界里&#xff0c;非易失性存储技术扮演着至关重要的角色。MTD&#…

Spring Aop 源码解析(下)

ProxyFactory选择cglib或jdk动态代理原理 ProxyFactory在生成代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术: config就是ProxyFactory对象,把自己传进来了,因为ProxyFactory继承了很多类,其中一个父类就是ProxyConfig // config就是ProxyFactory对象// 是不是…

开发npm上传发布

第一步&#xff1a;注册npm账号 首先去官网注册一个npm账号&#xff0c;npm官网 第二步&#xff1a;创建项目 新建文件夹&#xff0c;并执行npm init 填写对应的信息name就是插件名称。 文件夹下就会生成一个package.json文件。 你可以在项目编辑你的插件。 第三步&…

第十二届蓝桥杯物联网试题(省赛)

思路&#xff1a; 这个考了一个RTC的配置&#xff0c;RTC我只配过一次&#xff0c;所以有些生疏&#xff0c;还是不能大意&#xff0c;一些偏僻的考点还是要多练&#xff0c;在获取RTC时间的时候也遇到一些bug,这个后续会用一篇博客将最近遇到的BUG都总结一下 主要的难点还是…

wordpress将图片默认连接到媒体文件

wordpress上传图片后&#xff0c;图片链接可以选择链接到媒体文件或附件页面。如果选择链接到媒体文件&#xff0c;就是链接到了图片的地址了。如果选择链接到附件页面&#xff0c;就是链接到图片所在的attachment页面了。 具体链接到哪里&#xff0c;在wordpress模板制作时&a…