学习笔记——差分

差分

差分(difference)又名差分函数或差分运算,差分的结果反映了离散量之间的一种变化,是研究离散数学的一种工具。它将原函数f(x) 映射到f(x+a)-f(x+b) 。差分运算,相应于微分运算,是微积分中重要的一个概念。总而言之,差分对应离散,微分对应连续。差分又分为前向差分、向后差分及中心差分三种。
(上面概念蒟蒻都不懂/kk)

一维差分

一维差分中,差分就是将数列中的每一项分别与前一项数做差
例如 1 2 3 4 5
差分后 1 1 1 1 1 -5;
就是这样的。
那么一维差分有显而易见的性质
1、差分序列求前缀和可得原序列
2、将原序列区间[L,R]中的元素全部+1,可以转化操作为差分序列L处+1,R+1处-1
3、按照性质2得到,每次修改原序列一个区间+1,那么每次差分序列修改处增加的和减少的相同

二维差分(这里引用了一篇博客)

例题在luoguP3397
二维差分和一维差分思路上并没有什么区别,具体实现的区别就在于一维的直接对区间两端差分就好了,而二维的多了一维需要处理。
二维前缀和公式:sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]
二维只需要在每一个差分点都差分一次!

树上差分

引用自
引用自

树上差分,就是利用差分的性质,对路径上的重要节点进行修改(而不是暴力全改),作为其差分数组的值,最后在求值时,利用dfs遍历求出差分数组的前缀和,就可以达到降低复杂度的目的。

树上差分时需要求LCA

对点和边的树上差分原理相同,实现略有不同,这里分开来讲。

点差分

点差分
设将两点u,v之间路径上的所有点权增加x,o=LCA(u,v),o的父亲节点为p,则操作如下:

d i f f [ u ] + = x , d i f f [ v ] + = x , d i f f [ o ] − = x , d i f f [ p ] − = x ; diff[u]+=x,diff[v]+=x,diff[o]-=x,diff[p]-=x; diff[u]+=x,diff[v]+=x,diff[o]=x,diff[p]=x;
怎么样,是不是很简单!原理也很简单,举个例子:

设原树如下,现要将2,3之间路径上的所有点的权值增加3,设原权值均为0。
在这里插入图片描述
大家现在一定会想像差分数组从前往后扫一样从根往下扫,每个点存它与它的父亲的差,但是认真想一下,这样会存在一个问题,如果我将一条路径上每个点的值都增加k,那么这条路径上的其它枝杈都要打标记减去k。

这样当路径上的枝杈过多时,时间复杂度会非常不优。

那么应该怎么办呢?我们思考一下刚开始学OI的时候学到的递归思想来解决这个问题。

那么现在我们定义一个节点u的差分数组B[u]表示它与它所有儿子的加和的差,那么问题就变得简单多,我们只需要在最后统计答案的时候递归处理即可。

那么相比很多人有些疑惑,我们应该怎么做修改呢?

还是那个问题,现在我们要将两个点的最短路径上的点都加k或者减k,暂且设这两个点为u,v。

那么我们还需要再定义两个点,u和v的LCA为lca(倍增或Tarjan求出),lca的直接父亲为father。

那么我们在更改的时候只需要做如下操作:

B[u]+=k;

B[v]+=k;

B[lca]-=k;

B[father]-=k;
  
那么为什么这么做是正确的呢?

我们可以认为我们在给u节点的差分数组+k的时候也就相当与将u到根的所有节点都加了k,给v节点的修改同理。

那么我们需要将多更改的部分减去,多更改的部分也就是lca多更改了一次,从father到跟节点多更改了两次,所以我们在将B[lca]-=k,B[father]-=k同时就相当于是做了这个操作(B[lca]-=k相当与减掉了lca多更改的那一次和father到跟节点多更改的一次,B[father]-=k相当于是剪掉了father到跟节点多更改的剩下的那一次,叠加即为减去了多更改的部分)。

当所有的操作都完成后只需要DFS递归统计答案即可。

修改后 成了下图
在这里插入图片描述

边差分

将两点u,v之间路径上的所有边权增加x,o=LCA(u,v),以每条边两端深度较大的节点存储该边的差分数组,则操作如下:

d i f f [ u ] + = x , d i f f [ v ] + = x , d i f f [ o ] − = 2 ∗ x ; diff[u]+=x,diff[v]+=x,diff[o]-=2*x; diff[u]+=x,diff[v]+=x,diff[o]=2x;
再举个例子,还是上面那个图

则操作后有:
在这里插入图片描述

模板
Luogu P3128

Luogu P2680

LuoguP3258

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 jQuery 的事件,我可以和你分享一些学习笔记。 1. 绑定事件 在 jQuery 中,我们可以通过以下方式来绑定事件: ``` $(selector).event(function(){ // 事件处理程序 }) ``` 其中,`selector` 表示要绑定事件的元素,`event` 表示要绑定的事件类型,比如 `click`、`mouseover` 等等。事件处理程序则是在事件触发时要执行的代码块。 2. 多个事件绑定 我们可以通过 `on()` 方法来同时绑定多个事件: ``` $(selector).on({ event1: function(){ // 事件处理程序1 }, event2: function(){ // 事件处理程序2 } }) ``` 这样,当 `event1` 或 `event2` 中任意一个事件触发时,对应的处理程序都会被执行。 3. 解除事件 如果需要解除某个元素的事件处理程序,可以使用 `off()` 方法: ``` $(selector).off(event); ``` 其中,`event` 表示要解除的事件类型。如果不指定事件类型,则会解除该元素上所有的事件处理程序。 4. 事件委托 在 jQuery 中,我们可以使用事件委托来提高性能。事件委托是指将事件绑定到父元素上,而不是绑定到子元素上,然后通过事件冒泡来判断是哪个子元素触发了该事件。这样,当子元素数量较多时,只需要绑定一次事件,就可以监听到所有子元素的事件。 ``` $(selector).on(event, childSelector, function(){ // 事件处理程序 }) ``` 其中,`selector` 表示父元素,`event` 表示要绑定的事件类型,`childSelector` 表示要委托的子元素的选择器,事件处理程序则是在子元素触发事件时要执行的代码块。 以上是 jQuery 中事件的一些基本操作,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值