不是很明白,如果把lazy标记换成任务队列(暂时别管内存),这个题也应该是可以做的吧。。。 代码相当长。。。有点麻烦
import copy
n, m, p = map(int, input().split())
class node:
def __init__(self, val, a, b, left=None, right=None, lazy=None):
self.val = val
self.interval = (a, b)
self.left = left
self.right = right
self.lazy = lazy if lazy else []
self.interval_len = b - a + 1
def __str__(self):
return "[%2d,%2d] val=%3d lazy=%s" % (self.interval[0], self.interval[1], self.val, self.lazy.__str__())
def build(li: list, l: int, r: int) -> node:
if l == r:
return node(li[l], l, r)
mid = l + r >> 1
lp, rp = build(li, l, mid), build(li, mid + 1, r)
return node(lp.val + rp.val, l, r, left=lp, right=rp)
def preOrder(root):
if not root:
return
print(root)
preOrder(root.left)
# if root.left is None and root.right is None:
preOrder(root.right)
def cover(li1, li2): # 1 区间覆盖2 区间
return li1[0] <= li2[0] <= li2[1] <= li1[1]
def has_common(li1, li2): # 1和2有公共元素
return not (li1[0] <= li1[1] < li2[0] <= li2[1] or li2[0] <= li2[1] < li1[0] <= li1[1])
def change(root, op, interval, val):
if cover(interval, root.interval):
root.lazy.append((op, val))
if root.interval_len == 1:
while root.lazy:
a, b = root.lazy.pop()
if a == 1:
root.val *= b
else:
root.val += b * root.interval_len
return root
if root.left and has_common(interval, root.left.interval):
root.left = change(root.left, op, interval, val)
if root.right and has_common(interval, root.right.interval):
root.right = change(root.right, op, interval, val)
return root
def pushdown(root): # 如果还有子节点,那么下传,否则就到叶子结点为止
if root.left and root.right:
root.left.lazy += copy.deepcopy(root.lazy)
root.right.lazy += copy.deepcopy(root.lazy)
while root.lazy:
a, b = root.lazy.pop(0)
if a == 1:
root.val *= b
else:
root.val += b * root.interval_len
return root, root.val
def update(root): # 有时候,查询节点A时,A不带lazy标记,但是A的子节点带有标记,
# 那么是否就要整个更新A子树?
if root is None:
return None
if root.lazy and root.left and root.right:
root.left.lazy += copy.deepcopy(root.lazy)
root.right.lazy += copy.deepcopy(root.lazy)
while root.lazy:
a, b = root.lazy.pop(0)
if a == 1:
root.val *= b
else:
root.val += b * root.interval_len
root.left = update(root.left)
root.right = update(root.right)
if root.left:
root.val = 0
root.val += root.left.val
root.val += root.right.val
return root
def query(root, interval): # 询问区间interval
if cover(interval, root.interval):
root = update(root)
return root, root.val
if root.lazy:
root, res = pushdown(root)
ans = 0
# print(root)
if root.left and has_common(root.left.interval, interval):
root.left, temp = query(root.left, interval)
ans += temp
if root.right and has_common(root.right.interval, interval):
root.right, temp = query(root.right, interval)
ans += temp
# print(root.left, root.right)
root.val = root.left.val + root.right.val
return root, ans
li = list(map(int, input().split()))
root = build(li, 0, len(li) - 1)
for i in range(m):
t = list(map(int, input().split()))
if t[0] == 3:
root, ans = query(root, [t[1] - 1, t[2] - 1])
print(ans % p)
else:
root = change(root, t[0], [t[1] - 1, t[2] - 1], t[3])
preOrder(root)
# root = update(root)
# inOrder(root)