差分(区间修改求最小值高效)

做到一道需要多次改变一个 数组 一个区间的值的题目,暴力地for一遍的话肯定会T掉
然后经过学长的讲解,差分 这个小可爱 就进入了我的视野中。

什么是差分
一个序列 1 2 3 4 5
把这个序列进行差分运算 就是使这个序列中每一个数字(除了第一个数字)变为这个数字本身减去他前一个数字的差

  • 因为第一个数字没有前一个数字,所以差分运算后第一个数字不变

所以这个序列进行差分运算之后就变为 1 、2-1 、 3-2 、 4-3 、 5-4也就是1 1 1 1 1
这样看来差分运算似乎并没有什么稀奇的,但是它的性质很神奇鸭!

差分神奇的性质

我们把差分过程抽象出来 把它一般化
有一个序列a1,a2,a2…an
对它进行差分 就变成了a1 ,a2-a1 ,a3-a2…,an-a(n-1) <–这个括号里是指下标,大家自行理解一下叭
差分后的序列 前i项和
sum=a1+(a2-a1)+(a3-a2)+…+(a(i-1)-a(i-2))+(ai-a(i-1))
=a1+a2-a1+a3-a2+…+a(i-1)-a(i-2)+ai-a(i-1)
相信聪明的大家一定发现了1i - 1 项都被消掉了,最后只剩下了ai
这就是差分神奇的性质啦
差分后序列的前 i 项和等于差分前第 i 个元素(咳咳,敲黑板啦!)

区间修改+求最小值

讲完了差分这个神奇的性质,然后还要讲一个差分在数组区间修改中的一个神操作

还是刚才的那个序列1 2 3 4 5
如果现在需要对这个序列的 [ l,r ] 区间上所有元素都加上x,并且要进行多次这样的操作,最后来求这整个序列的最小值。

大家一开始可能都会想到暴力for一遍 [ l, r ] 来修改区间元素值,但是这样时间效率实在是太低了,如果每一次操作区间都是1到n,并且操作次数很多的话就很容易T掉,所以我们就要寻求一下更简单的做法,大家不可以这么暴力,我们要对电脑温柔一点w

这时候就要用到我们的差分啦

首先我们还是举例说明,说清楚之后再推广到一般
初始序列 1 2 3 4 5
初始差分序列 1 1 1 1 1

如果需要对第2到4个数进行加1的操作
操作后 1 3 4 5 5
操作后差分序列 1 2 1 1 0

我们盯着第2到4个数的操作前后的差分序列看,有木有发现什么神奇的事情
大家可以试一试其他的观察一下

扫描二维码关注公众号,回复: 11143711 查看本文章

观察后我们发现:
操作改变的区间,只有区间第一个元素,以及区间最后一个元素的后一个元素的差分结果改变,其他差分结果均不改变

可能有点绕口,大家结合上面的例子再咀嚼一下下下。
这是为神魔捏
这是可是有理有据的,believe me ,please!

我们现在推广到一般证明一下子
原序列为a1 , a2 , a3 , … , aL , a(L+1) , … , a(R-1) , aR , … , a(n-1) , an
原差分序列为
a1 , (a2-a1) , (a3-a2) , … , ( aL - a(L-1) ) , ( a(L+1) - aL), … , ( a(R-1) - a(R-2) ) , ( aR - a(R-1) ) , ( a(R+1) - aR ) , … , ( a(n-1) - a(n-2) ) , ( an - a(n-1) )
现在要对区间 [ L , R ] 进行加 x 的操作
操作后序列变为a1,a2,a3,…,aL+x , a(L+1)+x , … , a(R-1)+x , aR+x , … , a(n-1) , an
操作后差分序列变为
a1 , (a2-a1) , (a3-a2) , … , ( aL - a(L-1) )+x , ( a(L+1) - aL) , … , ( a(R-1) - a(R-2) ) ,
( aR - a(R-1) ) , ( a(R+1) - aR )-x , … , ( a(n-1) - a(n-2) ) , ( an - a(n-1) )

原因如下

  • 区间【L,R】内每个元素都加上了相同的值,所以相对差距并没有改变,所以【L+1,R】的差分值并没有改变,但是这个区间的两头却会发生改变
  • 第L个元素加上了x,但第L-1个元素没有加x,所以第L个元素的差分结果就会从原来的 ( aL - a(L-1) )变成了现在的( aL -
    a(L-1) )+x 。增加了x
  • 同理尾部第R个元素加上了x,但是第R+1个元素没有加x,所以第R+1个元素的查分结果就从原来的( a(R+1) - aR )变成了现在的(
    aR - a(R-1) ) , ( a(R+1) - aR )-x 。减少了x

这样的发现让我们的区间修改摇身一变变成了O(1)的操作
(O(1)啊!!!!是不是很诱人!!!)

Solution

我们对于这样的问题

  1. 首先,得出初始差分序列
  2. 在初始差分序列上根据每一次操作,修改操作区间第一个元素,使它加x,修改区间最后一个元素的后一个元素,使它减去x。
  3. 多次操作完成后,根据多次操作后的差分序列,结合上面讲到的差分序列的性质,还原出经过多次操作后的数列,for一遍找出最小值即可

萌新第一次写博客,如有不够完善之处,敬请指正!

发布了12 篇原创文章 · 获赞 23 · 访问量 1789

猜你喜欢

转载自blog.csdn.net/qq_43816486/article/details/89163784