-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfenwick.py
131 lines (98 loc) · 3.29 KB
/
fenwick.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from typing import List
print('fenwick')
class FenwickTree:
'''
Fenwick Tree (Binary Indexed Tree)
Fenwick Tree is a data structure that can efficiently update elements
and calculate prefix sums in a table of numbers.
'''
def __init__(self, nums: List[int]):
'''
Initialize the Fenwick Tree with the given array of numbers.
Time complexity: :math:`O(n)`, where n is the number of elements in the array.
Space complexity: :math:`O(n)`, where n is the number of elements in the array.
:type nums: List[int]
:rtype: None
'''
self.size = len(nums)
self.tree = [0] * (self.size + 1)
self.data = [0] * (self.size)
for i in range(self.size):
self.update(i, nums[i])
def update(self, index: int, val: int) -> None:
'''
Update the value of the element at index i to be val.
Time complexity: :math:`O(\log n)`, where n is the number of elements in the array.
Space complexity: :math:`O(1)`
:type index: int
:type val: int
:rtype: None
'''
# Calculate the delta
delta = val - self.data[index]
self.data[index] = val
# Increment the index to match the 1-based index of the Fenwick Tree
index += 1
while index <= self.size:
self.tree[index] += delta
index += index & -index
def pref(self, index: int) -> int:
'''
Calculate the prefix sum up to index i.
Time complexity: :math:`O(\log n)`, where n is the number of elements in the array.
Space complexity: :math:`O(1)`
:type index: int
:rtype: int
'''
index += 1
result = 0
while index > 0:
result += self.tree[index]
index -= index & -index
return result
def sumRange(self, left: int, right: int) -> int:
'''
Calculate the sum of elements from index l to r (with 0-based indexing).
Time complexity: :math:`O(\log n)`, where n is the number of elements in the array.
Space complexity: :math:`O(1)`
:type left: int
:type right: int
:rtype: int
'''
return self.pref(right) - self.pref(left-1)
nums = [1, 3, 5, 7, 9, 11]
fenwick = FenwickTree(nums)
print(fenwick.sumRange(0, 2))
fenwick.update(1, 2)
print(fenwick.sumRange(0, 2))
print(fenwick.tree)
print(fenwick.data)
# class Fenwick:
# def __init__(self, n, nums=None):
# self.n = n
# self.arr = [0 for _ in range(n + 1)]
# if nums:
# self.arr[1:] = nums
# self.__build()
# def __build(self):
# for i in range(1, self.n):
# if i + (i & -i) <= self.n:
# self.arr[i + (i & -i)] += self.arr[i]
# def add(self, idx, dlt):
# idx += 1
# while idx <= self.n:
# self.arr[idx] += dlt
# idx += idx & -idx
# def query(self, ql, qr):
# # [ql, qr)
# return self.pref(qr) - self.pref(ql)
# def pref(self, qr):
# # [0, qr)
# ans = 0
# while qr:
# ans += self.arr[qr]
# qr -= qr & -qr
# return ans
# def suff(self, ql):
# # [ql, n)
# return self.pref(self.n) - self.pref(ql)