差分算法(用python语言实现)

一.差分

1.介绍

一般地,差分主要用于多次将某个序列的某一段加上或减去某一特定值。相对于一个元素一个元素地加,大大减少了时间复杂度

2.定义

差分可以见简单看成序列中每一个元素与其前一个元素的差

3.差分与前缀和

   一般地,我们认为原序列就是差分序列的前缀和,所以把差分看做前缀和的逆运算

二.一维差分

1.定义

一维差分是指给定一个长度为n的序列a,要求支持操作pro(l,r,c)表示对a[l]~a[r]区间上的每一个值都加上或减去常数c,并求修改后的序列a。(注:我们是借助差分这个工具来对原序列的某一段进行改变,所以最终的结果还是要反映到原序列上的)

2.作用

可以将对a数组任意区间的同一操作优化到O(1)。

举个栗子:

如果我想对如下序列的子序列2~6的这一段数据上加上3,为4~8这一段的数据都加上2

l=[0,2,3,5,6,7,7,8,9,10,1,2]


l=[0,2,3,5,6,7,7,8,9,10,1,2]
for i in range(2,7):
  l[i]+=3
for i in range(4,9):
  l[i]+=2
for i in range(12):
  print(l[i])

#在这里我们只要求将给两段上加上了特定的值
#但是如果我们要求给n个子序列上加上特定的值  并且每个子序列的中的元素都不小于m
#那么我们就要遍历长度不小于的m序列 并且要遍历n次  时间复杂度为O(m*n) 就会特别耗时

但是如果用差分的话就会简便很多:


def insert(b,l,r,c):
  b[l]+=c
  b[r+1]-=c

if __name__ == "__main__":
  l=[0,2,3,5,6,7,7,8,9,10,1,2] 
  l,r,c=map(int,input().split())
  insert(b,2,6,3)#如果我子序列中有m个元素 那么这里直接从O(m)降到了O(1)
  insert(b,4,8,2)
  for i in range(1,12):
    b[i]+=b[i-1]
  for i in range(1,12):
    a[i]+=b[i]
    print(a[i],end=' ')

3.两种模板

 1.先构建原序列差分数组,然后直接在差分数组上进行操作,最后直接求出此差分数组的前缀和,便是最后的经过几波操作后的结果序列。

 2.开始将差分数组都赋值为0,然后对差分数组进行操作,最后将差分数组的前缀和与原数组相加便是最后的结果。

4.实战演练

题目链接:https://www.acwing.com/problem/content/799/

用第一个模板写


def insert(b,l,r,c):
  b[l]+=c
  b[r+1]-=c

if __name__ == "__main__":
  n,m=map(int,input().split())
  a=[0]*(n+10)#元序列
  b=[0]*(n+10)#差分序列
  nums=list(map(int,input().split()))
  for index,val in enumerate(nums):#这里的enumerate函数可以直接罗列出此列表中的下标和元素
    a[index+1]=val

  for i in range(m):
    l,r,c=map(int,input().split())
    insert(b,l,r,c)
  for i in range(1,n+1):
    b[i]+=b[i-1]#求差分序列的前缀和
  for i in range(1,n+1):
    a[i]+=b[i]#再将两个序列相加  将差分序列的作用反映到原序列上
    print(a[i],end=' ')

用第二个模板写

def insert(b, l, r, c):
    b[l] += c
    b[r+1] -= c

if __name__ == "__main__":
    n, m = map(int, input().split())
    a = [0] * (n + 10)  
    b = [0] * (n + 10)  #
    nums = list(map(int, input().split()))
    for index, val in enumerate(nums):
        a[index+1] = val
    for i in range(1, n+1):  
        insert(b, i, i, a[i])#构造差分序列
    while m > 0:
        m -= 1
        l, r, c = map(int, input().split())
        insert(b, l, r, c)
    for i in range(1, n+1):
        b[i] += b[i-1]
        print(b[i],end=" ")#直接输出差分序列的前缀和就好

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值