@@ -121,73 +121,73 @@ export default {
121
121
{
122
122
language : "py" ,
123
123
text : `
124
- class LazySegmentTree:
125
- def __init__(self, data):
126
- '''
127
- data:传入的数组
128
- '''
129
- self.data = data
130
- self.n = len(data)
131
- # 申请4倍data长度的空间来存线段树节点
132
- self.tree = [0] * (4 * self.n) # 索引i的左孩子索引为2i+1,右孩子为2i+2
133
- # 要点 1 开始
134
- self.dirty = [True] * (4 * self.n) # 索引i的左孩子索引为2i+1,右孩子为2i+2
135
- # 要点 1 结束
136
- if self.n:
137
- self.build(0, 0, self.n-1)
138
-
139
- def build(self, tree_index, l, r):
140
- if l == r:
141
- self.tree[tree_index] = self.data[l]
142
- return
143
- left, right = 2 * tree_index + 1, 2 * tree_index + 2
144
- mid = (l + r) // 2
145
- self.build(left, l, mid)
146
- self.build(right, mid+1, r)
147
- self.tree[tree_index] = self.tree[left] + self.tree[right]
148
-
149
- def updateSum(self, ql, qr):
150
- self.update(0, 0, self.n-1, ql, qr)
151
-
152
- def update(self, tree_index, l, r, ql, qr):
153
- if l == ql and r == qr:
154
- # 要点 2 开始
155
- self.dirty[tree_index] = not self.dirty[tree_index]
156
- self.tree[tree_index] = r - l + 1 - self.tree[tree_index]
157
- # 要点 2 结束
158
- return
159
- left, right = 2 * tree_index + 1, 2 * tree_index + 2
160
- mid = (l + r) // 2
161
- # 要点 3 开始
162
- if not self.dirty[tree_index]: # 如果有标记就处理
163
- self.update(left, l, mid, l, mid)
164
- self.update(right, mid+1, r, mid+1, r)
165
- self.dirty[tree_index] = True # 重置回去
166
- # 要点 3 结束
167
- if qr <= mid: self.update(left, l, mid, ql, qr)
168
- elif ql > mid: self.update(right, mid+1, r, ql, qr)
169
- else:
170
- self.update(left, l, mid, ql, mid)
171
- self.update(right, mid+1, r, mid+1, qr)
172
- self.tree[tree_index] = self.tree[left] + self.tree[right]
173
-
174
- def querySum(self, ql, qr):
175
- return self.query(0, 0, self.n-1, ql, qr)
176
-
177
- def query(self, tree_index, l, r, ql, qr):
178
- if l == ql and r == qr:
179
- return self.tree[tree_index]
180
- left, right = 2 * tree_index + 1, 2 * tree_index + 2
181
- mid = (l + r) // 2
182
- # 要点 3 开始
183
- if not self.dirty[tree_index]: # 如果有标记就处理
184
- self.update(left, l, mid, l, mid)
185
- self.update(right, mid+1, r, mid+1, r)
186
- self.dirty[tree_index] = True # 重置回去
187
- # 要点 3 结束
188
- if qr <= mid: return self.query(left, l, mid, ql, qr)
189
- if ql > mid: return self.query(right, mid+1, r, ql, qr)
190
- return self.query(left, l, mid, ql, mid) + self.query(right, mid+1, r, mid+1, qr)
124
+ class LazySegmentTree:
125
+ def __init__(self, data):
126
+ '''
127
+ data:传入的数组
128
+ '''
129
+ self.data = data
130
+ self.n = len(data)
131
+ # 申请4倍data长度的空间来存线段树节点
132
+ self.tree = [0] * (4 * self.n) # 索引i的左孩子索引为2i+1,右孩子为2i+2
133
+ # 要点 1 开始
134
+ self.dirty = [True] * (4 * self.n) # 索引i的左孩子索引为2i+1,右孩子为2i+2
135
+ # 要点 1 结束
136
+ if self.n:
137
+ self.build(0, 0, self.n-1)
138
+
139
+ def build(self, tree_index, l, r):
140
+ if l == r:
141
+ self.tree[tree_index] = self.data[l]
142
+ return
143
+ left, right = 2 * tree_index + 1, 2 * tree_index + 2
144
+ mid = (l + r) // 2
145
+ self.build(left, l, mid)
146
+ self.build(right, mid+1, r)
147
+ self.tree[tree_index] = self.tree[left] + self.tree[right]
148
+
149
+ def updateSum(self, ql, qr, val ):
150
+ self.update(0, 0, self.n-1, ql, qr, val )
151
+
152
+ def update(self, tree_index, l, r, ql, qr, val ):
153
+ if l == ql and r == qr:
154
+ # 要点 2 开始
155
+ self.dirty[tree_index] = not self.dirty[tree_index]
156
+ self.tree[tree_index] = ( r - l + 1) * val
157
+ # 要点 2 结束
158
+ return
159
+ left, right = 2 * tree_index + 1, 2 * tree_index + 2
160
+ mid = (l + r) // 2
161
+ # 要点 3 开始
162
+ if not self.dirty[tree_index]: # 如果有标记就处理
163
+ self.update(left, l, mid, l, mid, val )
164
+ self.update(right, mid+1, r, mid+1, r, val )
165
+ self.dirty[tree_index] = True # 重置回去
166
+ # 要点 3 结束
167
+ if qr <= mid: self.update(left, l, mid, ql, qr, val )
168
+ elif ql > mid: self.update(right, mid+1, r, ql, qr, val )
169
+ else:
170
+ self.update(left, l, mid, ql, mid, val )
171
+ self.update(right, mid+1, r, mid+1, qr, val )
172
+ self.tree[tree_index] = self.tree[left] + self.tree[right]
173
+
174
+ def querySum(self, ql, qr):
175
+ return self.query(0, 0, self.n-1, ql, qr)
176
+
177
+ def query(self, tree_index, l, r, ql, qr):
178
+ if l == ql and r == qr:
179
+ return self.tree[tree_index]
180
+ left, right = 2 * tree_index + 1, 2 * tree_index + 2
181
+ mid = (l + r) // 2
182
+ # 要点 3 开始
183
+ if not self.dirty[tree_index]: # 如果有标记就处理
184
+ self.update(left, l, mid, l, mid)
185
+ self.update(right, mid+1, r, mid+1, r)
186
+ self.dirty[tree_index] = True # 重置回去
187
+ # 要点 3 结束
188
+ if qr <= mid: return self.query(left, l, mid, ql, qr)
189
+ if ql > mid: return self.query(right, mid+1, r, ql, qr)
190
+ return self.query(left, l, mid, ql, mid) + self.query(right, mid+1, r, mid+1, qr)
191
191
`
192
192
}
193
193
]
@@ -260,5 +260,72 @@ class SegmentTree:
260
260
} ,
261
261
] ,
262
262
} ,
263
+ {
264
+ text : '动态开点' ,
265
+ problems : [ {
266
+ id : 'maximum-sum-queries' ,
267
+ title : '2736. 最大和查询'
268
+ } ] ,
269
+ codes : [ {
270
+ language : 'py' ,
271
+ text : `
272
+ class Node:
273
+ def __init__(self, l, r):
274
+ self.left = None # 左孩子的指针
275
+ self.right = None # 右孩子的指针
276
+ self.l = l # 区间左端点
277
+ self.r = r # 区间右端点
278
+ self.m = (l + r) >> 1 # 中点
279
+ self.v = 0 # 当前值
280
+ self.add = 0 # 懒标记
281
+
282
+ class SegmentTree:
283
+ def __init__(self,n):
284
+ # 默认就一个根节点,不 build 出整个树,节省空间
285
+ self.root = Node(0,n-1) # 根节点
286
+
287
+ def update(self, l, r, v, node):
288
+ if l > node.r or r < node.l:
289
+ return
290
+ if l <= node.l and node.r <= r:
291
+ node.v = (node.r - node.l + 1) * v
292
+ node.add = v # 做了一个标记
293
+ return
294
+ self.__pushdown(node) # 动态开点。为子节点赋值,这个值就从 add 传递过来
295
+ self.update(l, r, v, node.left)
296
+ self.update(l, r, v, node.right)
297
+ self.__pushup(node) # 动态开点结束后,修复当前节点的值
298
+
299
+ def query(self, l, r,node):
300
+ if l > node.r or r < node.l:
301
+ return 0
302
+ if l <= node.l and node.r <= r:
303
+ return node.v
304
+ self.__pushdown(node) # 动态开点。为子节点赋值,这个值就从 add 传递过来
305
+ return self.query(l, r, node.left) + self.query(l, r, node.right)
306
+
307
+ def __pushdown(self,node):
308
+ if node.left is None:
309
+ node.left = Node(node.l, node.m)
310
+ if node.right is None:
311
+ node.right = Node(node.m + 1, node.r)
312
+ if node.add > 0:
313
+ node.left.v = (node.left.r - node.left.l + 1) * node.add
314
+ node.right.v = (node.right.r - node.right.l + 1) * node.add
315
+ node.left.add = node.add
316
+ node.right.add = node.add
317
+ node.add = 0
318
+
319
+ def __pushup(self,node):
320
+ node.v = node.left.v + node.right.v
321
+
322
+ def updateSum(self,index,val):
323
+ self.update(index,index,val,self.root)
324
+
325
+ def querySum(self,left,right):
326
+ return self.query(left,right,self.root)
327
+ `
328
+ } ]
329
+ }
263
330
] ,
264
331
} ;
0 commit comments