蓝桥杯之差分题型

一维差分

问题描述

给定一个长度为 nn 的序列 aa

再给定 mm 组操作,每次操作给定 33 个正整数 l,r,dl,r,d,表示对 al∼ralr​ 中的所有数增加 dd

最终输出操作结束后的序列 aa

Update:由于评测机过快,n,mn,m 于 2024-12-09 从 105105 加强至 2×1052×105,杜绝暴力通过本题。 

输入格式

第一行输入两个正整数 n,mn,m。(1≤n,m≤2×1051≤n,m≤2×105)

第二行输入 nn 个正整数 aiai​。(1≤i≤n,1≤ai≤1041≤in,1≤ai​≤104)。

接下来 mm 行,每行输入 33 个正整数 l,r,dl,r,d。(1≤l≤r≤n,−104≤d≤1041≤lrn,−104≤d≤104)。

输出格式

输出 nn 个整数,表示操作结束后的序列 aa

样例输入

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

样例输出

3 4 5 3 4 2

思路解析

1. 输入数据
  • 读取数组的长度 n 和操作的次数 m。

  • 创建两个数组:

    • a:存储原始数组的值。

    • sum:差分数组,用于记录每个位置的变化。

2. 构建差分数组
  • 遍历数组 a,计算差分数组 sum

    sum[i]=a[i]−a[i−1]
    • 解释

      • 差分数组 sum 的每个位置存储了当前元素与前一个元素的差值。

      • 通过差分数组,可以高效地对区间进行加法操作。

3. 处理区间加法操作
  • 对于每次操作,指定区间 [l,r] 和值 tmp:

    • 在差分数组 sum 中:

      • sum[l] += \text{tmp}:表示从位置 l 开始的区间增加 tmp。

      • sum[r+1] -= \text{tmp}:表示在位置 r+1 之后的区间减去 tmp,以抵消前面的增加操作。

    • 注意:如果 r+1 超出数组范围,则不需要减去 tmp。

4. 恢复原始数组
  • 遍历差分数组 sum,恢复更新后的数组 a

    a[i]=a[i−1]+sum[i]
    • 解释

      • 通过累加差分数组的值,可以恢复每个位置的最终值。

5. 输出结果
  • 输出更新后的数组 a

 代码实现

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);// 读取数组长度和操作次数int n = scan.nextInt();int m = scan.nextInt();// 创建数组存储原始数组和差分数组int[] a = new int[n + 1];int[] sum = new int[n + 1];// 输入数组并构建差分数组for (int i = 1; i <= n; i++) {a[i] = scan.nextInt();sum[i] = a[i] - a[i - 1];}// 处理区间加法操作for (int i = 1; i <= m; i++) {int l = scan.nextInt();int r = scan.nextInt();int tmp = scan.nextInt();// 对区间 [l, r] 进行更新sum[l] += tmp;if (r + 1 <= n) {sum[r + 1] -= tmp;}}// 恢复更新后的数组for (int i = 1; i <= n; i++) {a[i] = a[i - 1] + sum[i];System.out.print(a[i] + " ");}scan.close();}
}

总结

  1. 核心思路

    • 利用差分数组高效地处理区间加法操作。

    • 通过差分数组的累加恢复最终的数组。

  2. 关键步骤

    • 构建差分数组

      sum[i]=a[i]−a[i−1]
    • 处理区间加法

      sum[l]+=tmpsum[r+1]−=tmp(如果 r+1≤n)
    • 恢复数组

      a[i]=a[i−1]+sum[i]
  3. 优点

    • 时间复杂度:每次区间加法操作的时间复杂度为 O(1),恢复数组的时间复杂度为 O(n)。

    • 空间复杂度:额外空间复杂度为 O(n)。

二维差分

问题描述

给定一个 n×mn×m 大小的矩阵 AA。

给定 qq 组操作,每次操作为给定 55 个正整数 x1,y1,x2,y2,dx1​,y1​,x2​,y2​,d,Ax1,y1Ax1​,y1​​ 是子矩阵左上角端点,Ax2,y2Ax2​,y2​​ 是子矩阵右下角端点,你需要给其中每个元素都增加 dd。

输出操作结束后的矩阵 AA。

输入格式

第一行输入 33 个正整数 n,m,qn,m,q。(1≤n,m≤103,1≤q≤1051≤n,m≤103,1≤q≤105)

接下来 nn 行每行输入 mm 个整数,表示 Ai,jAi,j​。(−103≤Ai,j≤103,1≤i≤n,1≤j≤m)(−103≤Ai,j​≤103,1≤i≤n,1≤j≤m)

接下来 qq 行,每行输入 55 个正整数 x1,y1,x2,y2,dx1​,y1​,x2​,y2​,d。(1≤x1≤x2≤n,1≤y1≤y2≤m,−103≤d≤103)(1≤x1​≤x2​≤n,1≤y1​≤y2​≤m,−103≤d≤103)

输出格式

输出 nn 行 mm 个整数,表示操作结束后的矩阵 AA。

样例输入

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

思路解析

1. 输入数据
  • 读取矩阵的行数 n 和列数 m,以及操作的次数 q。

  • 创建两个二维数组:

    • a:存储原始矩阵的值。

    • sum:差分数组,用于记录每个位置的变化。

2. 构建差分数组
  • 遍历矩阵 a,计算差分数组 sum

    sum[i][j]=a[i][j]−a[i−1][j]−a[i][j−1]+a[i−1][j−1]
    • 解释

      • 差分数组 sum 的每个位置存储了当前元素与相邻元素的差值。

      • 通过差分数组,可以高效地对区间进行加法操作。

3. 处理区间加法操作
  • 对于每次操作,指定区间 [x1,y1] 到 [x2,y2] 和值 tmp:

    • 在差分数组 sum 中:

      • sum[x1][y1] += \text{tmp}:表示从位置 [x1,y1] 开始的区间增加 tmp。

      • sum[x2+1][y1] -= \text{tmp}:表示在位置 [x2+1,y1] 之后的区间减去 tmp,以抵消前面的增加操作。

      • sum[x1][y2+1] -= \text{tmp}:表示在位置 [x1,y2+1] 之后的区间减去 tmp,以抵消前面的增加操作。

      • sum[x2+1][y2+1] += \text{tmp}:表示在位置 [x2+1,y2+1] 之后的区间加上 tmp,以抵消前面的减法操作。

    • 注意:如果某个位置超出矩阵范围,则不需要进行操作。

4. 恢复原始矩阵
  • 遍历差分数组 sum,恢复更新后的矩阵 a

    a[i][j]=a[i−1][j]+a[i][j−1]−a[i−1][j−1]+sum[i][j]
    • 解释

      • 通过累加差分数组的值,可以恢复每个位置的最终值。

5. 输出结果
  • 输出更新后的矩阵 a

代码实现

import java.util.*;public class Main {static final int N = 1000 + 10;static int[][] a = new int[N][N];static int[][] sum = new int[N][N];// 差分操作函数public static void f(int x1, int y1, int x2, int y2, int tmp) {sum[x1][y1] += tmp;sum[x2 + 1][y1] -= tmp;sum[x1][y2 + 1] -= tmp;sum[x2 + 1][y2 + 1] += tmp;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取矩阵的行数、列数和操作次数int n = sc.nextInt();int m = sc.nextInt();int q = sc.nextInt();// 输入矩阵并构建差分数组for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {a[i][j] = sc.nextInt();sum[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];}}// 处理区间加法操作while (q-- > 0) {int x1 = sc.nextInt();int y1 = sc.nextInt();int x2 = sc.nextInt();int y2 = sc.nextInt();int tmp = sc.nextInt();f(x1, y1, x2, y2, tmp);}// 恢复矩阵并输出结果for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + sum[i][j];System.out.print(a[i][j] + " ");}System.out.println();}sc.close();}
}

总结

  1. 核心思路

    • 利用二维差分数组高效地处理区间加法操作。

    • 通过差分数组的累加恢复最终的矩阵。

  2. 关键步骤

    • 构建差分数组

      sum[i][j]=a[i][j]−a[i−1][j]−a[i][j−1]+a[i−1][j−1]
    • 处理区间加法

      sum[x1][y1]+=tmpsum[x2+1][y1]−=tmpsum[x1][y2+1]−=tmpsum[x2+1][y2+1]+=tmp
    • 恢复矩阵

      a[i][j]=a[i−1][j]+a[i][j−1]−a[i−1][j−1]+sum[i][j]
  3. 优点

    • 时间复杂度:每次区间加法操作的时间复杂度为 O(1),恢复矩阵的时间复杂度为 O(n×m)。

    • 空间复杂度:额外空间复杂度为 O(n×m)。

相关的习题练习

棋盘
问题描述

小蓝拥有 n×nn×n 大小的棋盘,一开始棋盘上全都是白子。小蓝进行了 mm 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)。请输出所有操作做完后棋盘上每个棋子的颜色。

输入格式

输入的第一行包含两个整数 nn,mm,用一个空格分隔,表示棋盘大小与操作数。

接下来 mm 行每行包含四个整数 x1x1​,y1y1​,x2x2​,y2y2​,相邻整数之间使用一个空格分隔,表示将在 x1x1​ 至 x2x2​ 行和 y1y1​ 至 y2y2​ 列中的棋子颜色取反。

输出格式

输出 nn 行,每行 nn 个 00 或 11 表示该位置棋子的颜色。如果是白色则输出 00,否则输出 11。

样例输入

3 3
1 1 2 2
2 2 3 3
1 1 3 3

样例输出

001
010
100

评测用例规模与约定

对于 3030% 的评测用例,n,m≤500n,m≤500 ;

对于所有评测用例,1≤n,m≤20001≤n,m≤2000,1≤x1≤x2≤n1≤x1​≤x2​≤n,1≤y1≤y2≤m1≤y1​≤y2​≤m。

思路解析

1. 输入数据
  • 读取棋盘的大小 n 和操作的次数 m。

  • 创建两个二维数组:

    • b:二维差分数组,用于记录每次翻转操作的影响。

    • s:二维前缀和数组,用于计算每个位置的翻转次数。

2. 处理翻转操作
  • 对于每次操作,指定矩形区域 [x1,y1] 到 [x2,y2]:

    • 在差分数组 b 中:

      • b[x1][y1] += 1:表示从位置 [x1,y1] 开始的区域增加一次翻转。

      • b[x2 + 1][y1] -= 1:表示在位置 [x2+1,y1] 之后的区域减去一次翻转,以抵消前面的增加操作。

      • b[x1][y2 + 1] -= 1:表示在位置 [x1,y2+1] 之后的区域减去一次翻转,以抵消前面的增加操作。

      • b[x2 + 1][y2 + 1] += 1:表示在位置 [x2+1,y2+1] 之后的区域加上一次翻转,以抵消前面的减法操作。

    • 注意:如果某个位置超出棋盘范围,则不需要进行操作。

3. 计算二维前缀和
  • 遍历差分数组 b,计算每个位置的翻转次数:

    s[i][j]=b[i][j]+s[i−1][j]+s[i][j−1]−s[i−1][j−1]
    • 解释

      • 通过累加差分数组的值,可以计算每个位置的翻转次数。

4. 确定最终状态
  • 遍历二维前缀和数组 s,判断每个位置的翻转次数的奇偶性:

    • 如果翻转次数为奇数,表示该位置的颜色被翻转了奇数次,最终状态为白色(假设初始状态为黑色)。

    • 如果翻转次数为偶数,表示该位置的颜色被翻转了偶数次,最终状态为黑色。

    • 输出每个位置的最终状态。

代码实现

import java.util.Scanner;public class Main {static final int N = 2000 + 10; // 假设最大值为2000,加上一些缓冲static int[][] b = new int[N][N]; // 二维差分数组,用于记录翻转操作的影响static int[][] s = new int[N][N]; // 二维前缀和数组,用于计算每个位置的翻转次数static int n, m;public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取输入n = sc.nextInt(); // 棋盘大小m = sc.nextInt(); // 操作次数// 处理每个翻转操作while (m-- > 0) {int x1 = sc.nextInt();int y1 = sc.nextInt();int x2 = sc.nextInt();int y2 = sc.nextInt();// 更新二维差分数组 bb[x1][y1] += 1;if (x2 + 1 < N) b[x2 + 1][y1] -= 1;if (y2 + 1 < N) b[x1][y2 + 1] -= 1;if (x2 + 1 < N && y2 + 1 < N) b[x2 + 1][y2 + 1] += 1;}// 计算二维前缀和并确定最终状态for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {// 计算二维前缀和s[i][j] = b[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];// 判断翻转次数的奇偶性,确定最终颜色System.out.print(s[i][j] % 2);}System.out.println(); // 换行}sc.close(); // 关闭输入流}
}

总结

  1. 核心思路

    • 利用二维差分数组高效地处理区间翻转操作。

    • 通过二维前缀和数组计算每个位置的翻转次数,判断奇偶性确定最终状态。

  2. 关键步骤

    • 处理翻转操作

      b[x1][y1]+=1b[x2+1][y1]−=1b[x1][y2+1]−=1b[x2+1][y2+1]+=1
    • 计算二维前缀和

      s[i][j]=b[i][j]+s[i−1][j]+s[i][j−1]−s[i−1][j−1]
    • 确定最终状态

      最终状态=s[i][j]%2
  3. 优点

    • 时间复杂度:每次翻转操作的时间复杂度为 O(1),计算前缀和的时间复杂度为 O(n2)。

    • 空间复杂度:额外空间复杂度为 O(n2)。

  自学蓝桥杯笔记,希望我们可以一起学习!

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

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

相关文章

深入剖析 C/S 与 B/S 架构及网络通信基础

目录 C/S 架构详解​ 概念与示例​ 优点​ B/S 架构详解​ 概念与示例​ 优势​ 缺点​ C/S 与 B/S 的区别​ 架构组成​ 使用场景​ 开发和维护​ 安全性​ 网络通信基础​ IP 地址​ MAC&#xff08;物理地址&#xff09;​ 端口​ 路由器​ 网关​ 子网掩…

常见免杀框架的使用(3款)---【AniYaGUI1.2.0、AV_Evasion_Tool掩日、FoxBypass_V1.0】

一、AniYaGUI1.2.0免杀框架 环境&#xff1a;虚拟机Win10 、云服务器 工具&#xff1a;Xshell、CobaltStrike 项目下载地址&#xff1a; https://github.com/piiperxyz/AniYa 1. 安装Go语言环境 确保Win10虚拟机安装 Golang 且环境变量中包含 go 否则⽆法编译&#xff08;注…

Apache HTTPD 换行解析漏洞

漏洞介绍 CVE-2017-15715 Apache HTTPD 是一个广泛使用的 HTTP 服务器&#xff0c;可以通过 mod_php 模块来运行 PHP 网页。在其 2.4.0 到 2.4.29 版本中存在一个解析漏洞&#xff0c;当文件名以 1.php\x0A 结尾时&#xff0c;该文件会被按照 PHP 文件进行解析&#xff0c;这…

常用开发环境/工具版本选择(持续更新中)

操作系统&#xff1a;Ubuntu Server Version&#xff08;LTS&#xff09;Latest Sub VerRelease Time24.04(Noble Numbat)24.04.22025-02-1622.04(Jammy Jellyfish)22.04.52024-09-1120.04(Focal Fossa)20.04.62023-03-1418.04(Bionic Beaver)18.04.62021-09-1516.04.7(Xenial…

STM32 认识STM32

目录 什么是嵌入式&#xff1f; 认识STM32单片机 开发环境安装 安装开发环境 开发板资源介绍 单片机开发模式 创建工程的方式 烧录STM32程序 什么是嵌入式&#xff1f; 1.智能手环项目 主要功能有&#xff1a; 彩色触摸屏 显示时间 健康信息&#xff1a;心率&#…

C#核心笔记——(六)框架基础

我们在编程时所需的许多核心功能并不是由C#语言提供的,而是由.NET Framework中的类型提供的。本节我们将介绍Framework在基础编程任务(例如虚的等值比较、顺序比较以及类型转换)中的作用。我们还会介绍Framework中的基本类型,例如String、DateTime和Enum. 本章中的绝大部分…

AI——K近邻算法

文章目录 一、什么是K近邻算法二、KNN算法流程总结三、Scikit-learn工具1、安装2、导入3、简单使用 三、距离度量1、欧式距离2、曼哈顿距离3、切比雪夫距离4、闵可夫斯基距离5、K值的选择6、KD树 一、什么是K近邻算法 如果一个样本在特征空间中的k个最相似&#xff08;即特征空…

transient关键字深度解析

Java transient 关键字深度解析 transient(意思:瞬时的,瞬间的) 1. 核心概念 (1) 基本定义 作用:标记字段不参与序列化 适用场景: 敏感数据(如密码、密钥) 临时计算字段 依赖运行时环境的字段(如Thread对象) (2) 语法示例 java public class User implements Se…

信刻电子档案蓝光光盘刻录安全检测长期归档

信刻一直致力于为档案馆、各行业档案部门&#xff0c;提供跨网数据交换、电子档案数据磁光异质备份归档解决方案。所研制的电子档案光盘智能长期归档系统&#xff0c;满足国产环境下”刻、管、存、检、用”全生命周期管理应用需求&#xff0c;能够提供一份离线归档、一份近线存…

Word 中“母版页”的等效机制

Word 和 PowerPoint 不太一样——**Word 实际上没有像 PowerPoint 那样的“母版页&#xff08;Master Page&#xff09;”**功能。但它有1个和“母版页”功能类似的东西&#xff0c;可能造成你看到的“校徽自动出现在每一页”的现象&#xff1a; ✅ Word 中“母版页”的等效机制…

Go:反射

为什么使用反射 在编程中&#xff0c;有时需编写函数统一处理多种值类型 &#xff0c;这些类型可能无法共享同一接口、布局未知&#xff0c;甚至在设计函数时还不存在 。 func Sprint(x interface{}) string {type stringer interface {String() string}switch x : x.(type) …

SS25001-多路复用开关板

1 概述 1.1 简介 多路复用开关板是使用信号继电器实现2线制的多路复用开关板卡&#xff1b;多路复用开关是一种可以将一个输入连接到多个输出或一个输出连接到多个输入的拓扑结构。这种拓扑通常用于扫描&#xff0c;适合将一系列通道自动连接到公共线路的的设备。多路复用开…

vue3 nprogress 使用

nprogress 介绍与作用 1.nprogress 是一个轻量级的进度条组件&#xff0c;主要用于在页面加载或路由切换时显示一个进度条&#xff0c;提升用户体验。它的原理是通过在页面顶部创建一个 div&#xff0c;并使用 fixed 定位来实现进度条的效果 2.在 Vite Vue 3 项目中&#xf…

Jsp技术入门指南【六】jsp脚本原理及隐式对象

Jsp技术入门指南【六】jsp脚本原理及隐式对象 前言一、JSP 脚本元素1.1 声明1.2 表达式1.3 脚本标签 二、JSP 的隐式对象是什么三、隐式对象详解outrequestsessionapplicationconfigexception 前言 在之前的博客中&#xff0c;我们已经介绍了JSP的环境搭建、编译文件查找以及生…

vue3推荐的移动table库

vxe-table https://gitee.com/js-class/vxe-table#https://gitee.com/link?targethttps%3A%2F%2Fvxetable.cn 文档api https://vxetable.cn/#/component/table/other/bookkeepingVoucher 引入步骤 安装 npm install xe-utils vxe-tablenext 在项目main.js引入 import …

HOOPS Exchange 与HOOPS Communicator集成:打造工业3D可视化新标杆!

一、概述 在工业3D开发、BIM建筑、数字孪生和仿真分析等高端应用场景中&#xff0c;数据格式复杂、模型体量庞大、实时交互体验要求高&#xff0c;一直是困扰开发者的难题。Tech Soft 3D旗下的HOOPS Exchange和HOOPS Communicator&#xff0c;正是解决这类问题的黄金搭档。二者…

《软件设计师》复习笔记(14.3)——设计模式

目录 一、设计模式分类 1. 创建型模式&#xff08;Creational Patterns&#xff09; 2. 结构型模式&#xff08;Structural Patterns&#xff09; 3. 行为型模式&#xff08;Behavioral Patterns&#xff09; 真题示例&#xff1a; 一、设计模式分类 架构模式 高层设计决…

HarmonyOS:使用Refresh组件实现页面下拉刷新上拉加载更多

一、前言 可以进行页面下拉操作并显示刷新动效的容器组件。 说明 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。该组件从API Version 12开始支持与垂直滚动的Swiper和Web的联动。当Swiper设置loop属性为true时&…

55、⾸屏加载⽩屏怎么进⾏优化

答&#xff1a; &#xff08;1&#xff09;使⽤CDN 减⼩代码体积&#xff0c;加快请求速度&#xff1b; (2)SSR通过服务端把所有数据全部渲染完成再返回给客⼾端&#xff1b; (3) 路由懒加载&#xff0c;当⽤⼾访问的时候&#xff0c;再加载相应模块&#xff1b; (4) 使⽤外…

什么是Python单例模式

什么是Python单例模式 Python单例模式是一种创建型设计模式,目的是确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。以下从作用和示例进行介绍: 作用 控制资源使用:避免对系统资源的重复消耗,像数据库连接、文件句柄等稀缺资源,只创建一个实例来管理使用,防…