差分数组与树上差分

假设我们现在需要维护一段区间,实现对一段区间[L,R]的数的加/减,以及对区间中某个数的查询

最简单的方法把这段区间的数都记录到数组a[N]中,每次修改都对区间[L,R]的每一个数进行加减操作,然后在查询第k个数的时候返回a[k]

在上述算法中,修改操作的复杂度是o(n),而查询操作的复杂度是o(1)

这种操作在查询次数大,修改次数小的时候很高效

但在修改次数大,查询次数少的时候,就显得很慢了

那么在这个时候,我们可以使用差分数组来维护这段区间

差分数组:

我们定义一个新的数组d[N]

且d[i]满足转移式:

d[i]=a[i]-a[i-1],且d[0]等于0

也就是说,d[i]表示的是a[i]比其前面一个数大d[i]

那么在这个时候

假设我们需要对区间[l,r]的数都进行加k的操作,显然,区间[l+1,r]的d[i]的值都不变,因为在这个区间内的a[i]和a[i-1]都同时加上了k,所以他们的差值d[i]保持不变

而a[l]应该会比a[l-1]大k,a[r+1]应该会比a[r]小k

所以d[l]+=k;而d[r+1]-=k;

这样,就可以把对区间修改的时间复杂度降低到o(1)了

那么怎么进行查询呢?

观察d[i]的定义式,我们可以知道,a[x]=d[0]+d[1]+......d[x-1]+d[x]

所以,我们只需要o(n)的时间复杂度,把d数组的前x项求和,就可以得到a[x]的值了

树上差分:

上面提到的差分数组可以用来维护一维的区间

那么用同样的思路,我们也可以用差分的方法来维护树上的一段路径

我们现在定义树上的差分数组d[N]

假设现在有节点u和ls,rs,ls,rs是u的左右儿子

其中d[u]表示结点u的权值,那么d[u]=d[ls]+d[rs]

而d[ls]又可以分为d[ls的左儿子]+d[ls的右儿子]

这样无限递归直到叶子结点

我们类比一下上面的差分数组的单点查询,可以发现这非常的相似

我们对于树上一段路径的修改,是否也可以通过单点修改而降低时间复杂度呢?

答案是肯定的

我们这里将修改分为两种:

1.点修改

假定我们现在需要把路径(x,y)上的点的权值全部加k

对于x的父亲而言,只要x加了k,那么他自己自然也就加了k,这对x的父亲的父亲一样适用

对于y的父亲也是同理

那么x到y的路径中,一定包含了x的若干个祖先,y的若干个祖先,以及x和y的lca(最近公共祖先)

那么对于lca而言,他的值等于x的某个祖先的权值+y的某个祖先的权值,也就是说加了两次k

所以lca的sum应该减去k来抵消多加的一个k

而对于lca的父亲fa而言,他并没有加多一个k,但由于lca加多了一个k,所以fa也应该减去一个k

由此可以得到,对于修改路径(x,y)上的点权,假定为加k,那么就是:

d[x]+=k;d[y]+=k;d[lca(x,y)]-=k;d[fa(lca(x,y))]-=k;

2.边修改:

假定我们现在需要把路径(x,y)上的边权全部加k

由于对边的权值操作比较困难,我们将其下方到点权进行

对于这个下方操作,我们定义:

假定a是儿子,b是父亲,w是连接a与b的一条边,那么w的边权就等于d[b],同时,d数组的定义与上面的点修改中提到的一致

那么我们只需要让d[x]+=k;d[y]+=k;

这样子的话,对于路径(x,y)上的连接x的祖先们的边,连接y的祖先们的边的权值自然也就加上了k

但是对于lca(x,y)而言,由于他一条连接着x的祖先的边权加了k,另一条连着y的祖先的边权也加了k,为了不影响连接lca与其父亲的边权,所以d[lca(x,y)]需要减去2个k

总结就是:

d[x]+=k;d[y]+=k;d[lca(x,y)]-=2*k;

对于树上的单点修改,我们使用dfs即可

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

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

相关文章

数学建模 —— MATLAB中的矩阵(下)

目录 矩阵的拼接 矩阵的重复 矩阵的重构和重新排列 (1)reshape 函数 (2)sort 函数 (3)sortrows 函数 (4)flip / fliplr / flipud 函数 (5)rot90 函数 矩阵的拼接 有时候我们需要对多个矩阵进行拼接,变成一个大的矩阵。根据矩阵拼接的方向,我们可 …

C++性能优化篇:深拷贝、浅拷贝与移动构造

引言 最近在做性能优化,遇到了一个明显的性能问题,就是在大量数据做深拷贝的时候,程序耗时严重,几乎三分之一的时间都耗在了这里。于是乎仔细看了下此处的代码,发现这些深拷贝完全可以避免。 深拷贝、浅拷贝与移动构…

Java实现RS485串口通信

博客链接地址 近期,我接到了一个任务,将报警器接入到Java项目中,而接入的方式就是通过RS485接入,本人之前可以说是对此毫无所知。不过要感谢现在的互联网,通过网络我查到了我想要知道的一切,这里记录下本次…

对数据分析行业的疑问

我之前是做大数据的开发的,当然也做业务比如Java、springcloud的后端开发、也做了ai的。 但是我一直没怎么做数据分析,当我加入了新公司后发现,现在做大数据的大部分都是数据分析,用python和sql。 我今天一看他们的统计&#xf…

STM32音频应用开发:DMA与定时器的高效协作

摘要: 本文章将深入浅出地介绍如何使用STM32单片机实现音频播放功能。文章将从音频基础知识入手,逐步讲解音频解码、DAC转换、音频放大等关键环节,并结合STM32 HAL库给出具体的代码实现和电路设计方案。最后,我们将通过一个实例演示如何播放W…

NXP RT1060学习总结 - fsl_flexcan CAN FD 函数说明 -1

概要 CAN测试源码: https://download.csdn.net/download/qq_35671135/89425377 根据fsl_flexcan.h文件从文件末尾往前面梳理,总共CAN FD处理函数; 使用的是RT1064开发板进行测试。 1、中止中断驱动的消息接收进程(CAN FD) 函 数 &#xf…

揭示优化Prompt的秘诀:如何让API表现媲美网页版

为什么用GPT API(GPT-3.5-turbo)进行程序分析时,效果好像比网页版的GPT-3.5差一点?这可能有几个原因,咱们细说一下。 1. Prompt不同 这是最常见的问题之一。API调用时的指令(prompt)往往比较简…

Ceil()——向上取整函数

函数原型为: double ceil(double x); 大家可以在这个网站里更清晰的了解ceil - C Reference (cplusplus.com) 下面借助一道例题来帮助大家理解:牛牛的快递_牛客题霸_牛客网 (nowcoder.com) 我们分析题得知,在大于1的情况下,只要…

学懂C#编程:常用高级技术——学会Lambda表达式的应用(二)

上一篇介绍了Lambda基础的知识,接着我们通过讲解Lambda的几种应用场景来彻底学懂Lambda在编程中的应用。 Lambda表达式在C#中非常灵活,可以用在多种场合。以下是一些Lambda表达式示例,帮助你更全面地理解其用途: 1. 数组过滤&am…

【ocean】ocnPrin结合getData导出数据

核心就是这一句ocnPrint(?output fout leafValue( getData(“/output” ?result “dc”))) r_list list(4000, 4100, 4200) multi_list list(20,21,22) fout outfile("/home/yourpath/results.txt" "w") foreach(r_value r_listforeach(multi_value …

【Linux基础命令】文件管理命令(二)

文章目录 前言创建删除目录创建目录删除目录cp命令mv命令查看文件内容总结前言 在我们的上一篇文章中,我们介绍了一些基本的Linux文件管理命令,如 cd、ls 等。这些命令对于日常的文件操作任务非常有用。然而,Linux 提供的功能远不止这些。在本文中,我们将继续探索更多的文…

【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解

最终效果 文章目录 最终效果前言存储位置信息存储更多数据存储场景信息持久化存储数据完结 前言 前面写过小型游戏存储功能: 【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解(包含数据安全处理方案的加密解密) 这次做一…

基于RK3568车载电脑助力日本巴士公司高效完成巴士到站系统项目部署

无处不在的物联网(IoT)技术已经渗透到了人类生活的各个角落,如日常出行乘坐的公交车上,物联网(IoT)技术的应用就得到完美诠释!其通过公交车上的车载电脑网络与中控室服务器连接来对公交车的运行…

Vue-Ci搭建项目

项目创建 vue-cli 官方提供的一个脚手架,用于快速生成一个vue的项目模板;预先定义 好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个 骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速; 主要的功能 ● 统一的目录结构 ● 本地调试 热部署 ● 单元…

Rust详解日志

详解日志 相比起监控,日志好理解的多:在某个时间点向指定的地方输出一条信息,里面记录着重要性、时间、地点和发生的事件,这就是日志。 注意,本文和 Rust 无关,我们争取从一个中立的角度去介绍何为日志 日…

低代码开发平台:人人都可以开发应用

低代码开发平台是一种快速应用开发工具,它允许用户通过图形界面和模型驱动逻辑来构建应用程序,而不需要编写大量的代码。这种平台的目的是简化开发流程,降低技术门槛,使得非专业开发者也能快速构建应用程序。 低代码开发的优势 低…

IBM Spectrum LSF Application Center 提供单一界面来管理应用程序、用户、资源和数据

IBM Spectrum LSF Application Center 提供单一界面来管理应用程序、用户、资源和数据 亮点 ● 简化应用程序管理 ● 提高您的工作效率 ● 降低资源管理的复杂性 ● 深入了解流程 IBM Spectrum LSF Application Center 为集群用户和管理员提供了一个灵活的、以应用为中心的界…

openwrt igmp 适配

每弄完一次,过不多久就忘了,这次决心记下来。 openwrt 的igmpproxy 包是干嘛的?原来,组播包并不能穿透路由,也就是我们在wan端播放的组播视频流,lan端是没法收到的,igmpproxy就是用来打通wan端…

2024.6.26 刷题总结

2024.6.26 **每日一题** 526.优美的排列,该题考察的是状压dp的知识,用一个n位的二进制数表示排列中的数被选取的情况,若为1,则表示该位被选取,若为0,则表示该位没有被选取,用一个数组来存储当前…

STM32F1+HAL库+FreeTOTS学习1——FreeRTOS入门

STM32F1HAL库FreeTOTS学习1——FreeRTOS入门 裸机开发与操作系统嵌入式操作系统简介FreeRTOS简介FreeRTOS的几个重要概念任务调度器任务状态状态列表 裸机开发与操作系统 在以往的嵌入式学习中,我们最常用的就是裸机开发,所谓裸机开发就是指在没有操作系…