前缀和与差分

2020-03-12  本文已影响0人  madao756

0X00 一维前缀和

n, m = map(int, input().split())
nums = list(map(int, input().split()))
sums = [0] * (n+1)

for i in range(1, n+1):
    sums[i] = sums[i-1] + nums[i-1]
    
for _ in range(m):
    n1, n2 = map(int, input().split())
    print(sums[n2] - sums[n1-1])

0X01 二维前缀和

n, m = map(int, input().split())
nums = list(map(int, input().split()))
sums = [0] * (n+1)

for i in range(1, n+1):
    sums[i] = sums[i-1] + nums[i-1]
    
for _ in range(m):
    n1, n2 = map(int, input().split())
    print(sums[n2] - sums[n1-1])

0X02 一维差分

一维差分推导:

假设我们有数组 a[a_1, a_2, ..., a_n] 现在构造一个数组 b 使得:[a_1, a_2 - a_1, ..., a_n - a_{n -1}] 那么 b 的前 n 项和就是 a_n 并且如果我们向 b_k 增加一个数 c 那么再求 a_ka_n 的时候都会加上一个 c。因此我们完成了在 O(1) 的时间给一段数加上某一个数

现在我们来写它的模板:

差分只有一个操作 add,就是给一段区间加上一个值,

def add(l, r, v):
    b[r+1] -= v
    b[l] += v
n, q = map(int, input().split())
a = list(map(int, input().split()))
b = [0] * (n+1)

def add(l, r, v):
    b[r+1] -= v
    b[l] += v

for i, v in enumerate(a):
    add(i, i, v)

# print(b)
while q > 0:
    q -= 1
    l, r, v = map(int, input().split())
    add(l-1, r-1, v)

0X03 二维差分

构造一个二维数组 b 使得 b 的二维前缀和是 a

同样只有一个操作记住下面这张图:

想要绿色部分的 a 在 o(1) 的时间内全部加上 c 则只需要在 b 的图中 +c 的位置 +c -c 的位置 -c。就可以了

def add(x1,y1, x2, y2, v):
  b[x1][y1] += v
  b[x2+1][y1] -= v
  b[x1][y2+1] -= v
  b[x2+1][y2+1] += v
上一篇 下一篇

猜你喜欢

热点阅读