差分数组
差分数组是一种用于高效处理区间更新和查询的数据结构。它特别适用于需要对数组的某个区间进行多次更新,并且需要快速查询某个位置的值的场景。差分数组的核心思想是通过存储相邻元素的差值来简化区间更新操作。
差分数组的基本概念
假设有一个数组 a
,长度为 n
。差分数组 diff
是一个长度为 n+1
的数组,其中 diff[i]
表示 a[i]
和 a[i-1]
的差值。具体定义如下:
diff[0] = a[0]
diff[i] = a[i] - a[i-1]
,对于1 ≤ i < n
diff[n] = 0
(通常用于简化边界处理)
差分数组的构建
从原始数组 a
构建差分数组 diff
的过程如下:
diff = [0] * (n + 1)
diff[0] = a[0]
for i in range(1, n):
diff[i] = a[i] - a[i-1]
差分数组的应用
1. 区间更新
假设需要对数组 a
的区间 [L, R]
进行更新,将区间内的每个元素增加一个值 val
。使用差分数组可以高效地完成这个操作:
- 增加
val
到diff[L]
。 - 减少
val
从diff[R + 1]
。
这样,差分数组 diff
只需要修改两个位置,时间复杂度为 (O(1))。
2. 恢复原始数组
从差分数组 diff
恢复原始数组 a
的过程如下:
a = [0] * n
a[0] = diff[0]
for i in range(1, n):
a[i] = a[i-1] + diff[i]
3. 区间查询
如果需要查询某个位置 i
的值,可以直接从差分数组恢复:
a[i] = diff[0] + sum(diff[1:i+1])
但通常情况下,我们会在需要时直接从差分数组恢复整个数组,然后进行查询。
示例
假设有一个数组 a = [1, 2, 3, 4, 5]
,我们希望对区间 [1, 3]
进行更新,将每个元素增加2。
构建差分数组
a = [1, 2, 3, 4, 5]
n = len(a)
diff = [0] * (n + 1)
diff[0] = a[0]
for i in range(1, n):
diff[i] = a[i] - a[i-1]
print(diff) # 输出:[1, 1, 1, 1, 1, 0]
区间更新
对区间 [1, 3]
进行更新,将每个元素增加2:
L = 1
R = 3
val = 2
diff[L] += val
diff[R + 1] -= val
print(diff) # 输出:[1, 3, 1, 1, -1, -2]
恢复原始数组
a = [0] * n
a[0] = diff[0]
for i in range(1, n):
a[i] = a[i-1] + diff[i]
print(a) # 输出:[1, 4, 6, 8, 5]
优点
- 高效区间更新:差分数组可以在 (O(1)) 时间内完成区间更新操作。
- 简单易用:差分数组的实现和使用都非常简单,适合处理区间更新和查询问题。
适用场景
- 区间更新:频繁对数组的某个区间进行加减操作。
- 区间查询:需要快速查询某个位置的值。
题目练习
import os
import sys
from itertools import accumulate as acc
n,m=map(int,input().split())
diff=[0] * (n+1)
a=[]
for _ in range(m):
L,R=map(int,input().split())
L=L-1
R=R-1
diff[L]+=1 # 理解好差分数组的含义,这样做可以使得位置L比位置L-1多1,从L到R之间的关系不变,R+1比R多1
diff[R+1]-=1
a.append([L,R])
# 计算差分数组的前缀和,恢复数组,恢复后的数组就是假设全部执行,商品的库存量
b=list(acc(diff[:-1]))+[-1]
count_1=b.count(0)
for i,j in a:
count_2=b[i:j+1].count(1)
print(count_1+count_2)