Skip to content

Commit 2dbc9e5

Browse files
committed
segment-tree-lazy-propagation challenge
1 parent a440024 commit 2dbc9e5

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Challenge: Implement a segment tree that supports range queries and updates efficiently,
2+
# using lazy propagation to handle deferred updates without sacrificing performance.
3+
# Use object-oriented programming and follow the DRY principle.
4+
5+
from segment_tree import SegmentTree
6+
7+
def main():
8+
data = [1, 3, 5, 7, 9, 11]
9+
seg_tree = SegmentTree(data)
10+
11+
print("Initial sum of range [1, 3]:", seg_tree.query_range(1, 3))
12+
seg_tree.update_range(1, 5, 10)
13+
print("Sum of range [1, 3] after update:", seg_tree.query_range(1, 3))
14+
print("Sum of range [0, 5]:", seg_tree.query_range(0, 5))
15+
16+
if __name__ == "__main__":
17+
main()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from typing import List
2+
3+
class SegmentTree:
4+
def __init__(self, data: List[int]):
5+
self.n = len(data)
6+
self.tree = [0] * (4 * self.n)
7+
self.lazy = [0] * (4 * self.n)
8+
self._build(data, 0, 0, self.n - 1)
9+
10+
def _build(self, data: List[int], node: int, start: int, end: int):
11+
if start == end:
12+
self.tree[node] = data[start]
13+
else:
14+
mid = (start + end) // 2
15+
self._build(data, 2 * node + 1, start, mid)
16+
self._build(data, 2 * node + 2, mid + 1, end)
17+
self.tree[node] = self.tree[2 * node + 1] + self.tree[2 * node + 2]
18+
19+
def _update_range(self, node: int, start: int, end: int, l: int, r: int, val: int):
20+
if self.lazy[node] != 0:
21+
self.tree[node] += (end - start + 1) * self.lazy[node]
22+
if start != end:
23+
self.lazy[2 * node + 1] += self.lazy[node]
24+
self.lazy[2 * node + 2] += self.lazy[node]
25+
self.lazy[node] = 0
26+
27+
if start > r or end < l:
28+
return
29+
30+
if l <= start and end <= r:
31+
self.tree[node] += (end - start + 1) * val
32+
if start != end:
33+
self.lazy[2 * node + 1] += val
34+
self.lazy[2 * node + 2] += val
35+
return
36+
37+
mid = (start + end) // 2
38+
self._update_range(2 * node + 1, start, mid, l, r, val)
39+
self._update_range(2 * node + 2, mid + 1, end, l, r, val)
40+
self.tree[node] = self.tree[2 * node + 1] + self.tree[2 * node + 2]
41+
42+
def update_range(self, l: int, r: int, val: int):
43+
self._update_range(0, 0, self.n - 1, l, r, val)
44+
45+
def _query_range(self, node: int, start: int, end: int, l: int, r: int) -> int:
46+
if start > r or end < l:
47+
return 0
48+
49+
if self.lazy[node] != 0:
50+
self.tree[node] += (end - start + 1) * self.lazy[node]
51+
if start != end:
52+
self.lazy[2 * node + 1] += self.lazy[node]
53+
self.lazy[2 * node + 2] += self.lazy[node]
54+
self.lazy[node] = 0
55+
56+
if l <= start and end <= r:
57+
return self.tree[node]
58+
59+
mid = (start + end) // 2
60+
left_sum = self._query_range(2 * node + 1, start, mid, l, r)
61+
right_sum = self._query_range(2 * node + 2, mid + 1, end, l, r)
62+
return left_sum + right_sum
63+
64+
def query_range(self, l: int, r: int) -> int:
65+
return self._query_range(0, 0, self.n - 1, l, r)

0 commit comments

Comments
 (0)