Python | 差分数组 | 前缀和 | 蓝桥杯 | 商品库存管理

差分数组

差分数组是一种用于高效处理区间更新和查询的数据结构。它特别适用于需要对数组的某个区间进行多次更新,并且需要快速查询某个位置的值的场景。差分数组的核心思想是通过存储相邻元素的差值来简化区间更新操作。

差分数组的基本概念

假设有一个数组 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。使用差分数组可以高效地完成这个操作:

  • 增加 valdiff[L]
  • 减少 valdiff[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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值