Skip to content

Commit f46ce47

Browse files
authored
Add Max Fenwick Tree (TheAlgorithms#6298)
* Add `MaxFenwickTree` * Reformat code style * Fix type hints * Fix type hints again * Complete docstring * Complete docstring * Fix typo in file name * Change MaxFenwickTree into 0-based indexing * Fix Bugs * Minor fix
1 parent 063a0ec commit f46ce47

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
class MaxFenwickTree:
2+
"""
3+
Maximum Fenwick Tree
4+
5+
More info: https://cp-algorithms.com/data_structures/fenwick.html
6+
---------
7+
>>> ft = MaxFenwickTree(5)
8+
>>> ft.query(0, 5)
9+
0
10+
>>> ft.update(4, 100)
11+
>>> ft.query(0, 5)
12+
100
13+
>>> ft.update(4, 0)
14+
>>> ft.update(2, 20)
15+
>>> ft.query(0, 5)
16+
20
17+
>>> ft.update(4, 10)
18+
>>> ft.query(2, 5)
19+
10
20+
>>> ft.query(1, 5)
21+
20
22+
>>> ft.update(2, 0)
23+
>>> ft.query(0, 5)
24+
10
25+
>>> ft = MaxFenwickTree(10000)
26+
>>> ft.update(255, 30)
27+
>>> ft.query(0, 10000)
28+
30
29+
"""
30+
31+
def __init__(self, size: int) -> None:
32+
"""
33+
Create empty Maximum Fenwick Tree with specified size
34+
35+
Parameters:
36+
size: size of Array
37+
38+
Returns:
39+
None
40+
"""
41+
self.size = size
42+
self.arr = [0] * size
43+
self.tree = [0] * size
44+
45+
@staticmethod
46+
def get_next(index: int) -> int:
47+
"""
48+
Get next index in O(1)
49+
"""
50+
return index + (index & -index)
51+
52+
@staticmethod
53+
def get_prev(index: int) -> int:
54+
"""
55+
Get previous index in O(1)
56+
"""
57+
return index - (index & -index)
58+
59+
def update(self, index: int, value: int) -> None:
60+
"""
61+
Set index to value in O(lg^2 N)
62+
63+
Parameters:
64+
index: index to update
65+
value: value to set
66+
67+
Returns:
68+
None
69+
"""
70+
self.arr[index] = value
71+
while index < self.size:
72+
self.tree[index] = max(value, self.query(self.get_prev(index), index))
73+
index = self.get_next(index)
74+
75+
def query(self, left: int, right: int) -> int:
76+
"""
77+
Answer the query of maximum range [l, r) in O(lg^2 N)
78+
79+
Parameters:
80+
left: left index of query range (inclusive)
81+
right: right index of query range (exclusive)
82+
83+
Returns:
84+
Maximum value of range [left, right)
85+
"""
86+
right -= 1 # Because of right is exclusive
87+
result = 0
88+
while left < right:
89+
current_left = self.get_prev(right)
90+
if left < current_left:
91+
result = max(result, self.tree[right])
92+
right = current_left
93+
else:
94+
result = max(result, self.arr[right])
95+
right -= 1
96+
return result
97+
98+
99+
if __name__ == "__main__":
100+
import doctest
101+
102+
doctest.testmod()

0 commit comments

Comments
 (0)