def build(s, t, p):
"""
对 [s,t] 区间建立线段树
当前根的编号为 p
"""
if s == t:
d[p] = a[s]
return
m = s + ((t - s) >> 1)
build(s, m, p * 2)
build(m + 1, t, p * 2 + 1)
d[p] = d[p * 2] + d[(p * 2) + 1]
def getsum(l, r, s, t, p):
"""
[l, r] 为查询区间
[s, t] 为当前节点包含的区间
p 为当前节点的编号
"""
if l <= s and t <= r:
return d[p]
m = s + ((t - s) >> 1)
sum = 0
if l <= m:
sum = sum + getsum(l, r, s, m, p * 2)
if r > m:
sum = sum + getsum(l, r, m + 1, t, p * 2 + 1)
return sum
def update(l, r, c, s, t, p):
"""
[l, r] 为修改区间
c 为被修改的元素的变化量
[s, t] 为当前节点包含的区间
p 为当前节点的编号
"""
if l <= s and t <= r:
d[p] = d[p] + (t - s + 1) * c
b[p] = b[p] + c
return
m = s + ((t - s) >> 1)
if b[p] and s != t:
d[p * 2] = d[p * 2] + b[p] * (m - s + 1)
d[p * 2 + 1] = d[p * 2 + 1] + b[p] * (t - m)
b[p * 2] = b[p * 2] + b[p]
b[p * 2 + 1] = b[p * 2 + 1] + b[p]
b[p] = 0
if l <= m:
update(l, r, c, s, m, p * 2)
if r > m:
update(l, r, c, m + 1, t, p * 2 + 1)
d[p] = d[p * 2] + d[p * 2 + 1]
if __name__ == '__main__':
a = [0, 10, 11, 12, 13, 14]
n = len(a)-1
d = [0]*4*n
b = [0]*4*n
build(1, n, 1)
s = getsum(1, 3, 1, n, 1)
print("数组a", a)
print("数组d", d)
print("求和s", s)