I am trying to solve this question: https://open.kattis.com/problems/fenwick
A Fenwick Tree (also known as a Binary Indexed Tree) is a data structure on an array which enables fast (π(logπ)) updates and prefix sum queries on the underlying data.
For this problem, implement a Fenwick Tree to support operations of two types: (a) increment an element in the array or (b) query the prefix sum of a portion of the array.
Input The first line of input contains two integers π, π, where 1β€πβ€5000000 is the length of the array and 0β€πβ€5000000 is the number of operations. Then follow π lines giving the operations. There are two types of operations:
β+ π πΏβ indicates that π[π] is incremented by πΏ, where 0β€π<π and β10^9β€πΏβ€10^9 (both are integers)
β? πβ is a query for the value of π[0]+π[1]+β¦+π[πβ1], where 0β€πβ€π (for π=0 this is interpreted as an empty sum)
You should assume that every array entry is initially 0.
My implementation:
class SegmentTree:
def __init__(self, n):
self.nums = [0] * n
self.tree = {}
self._build()
def _build(self):
def build(l, r, index):
if l == r:
self.tree[index] = self.nums[l]
else:
mid = (l+r)//2
build(l, mid, index*2)
build(mid+1, r, index*2+1)
self.tree[index] = self.tree[index*2] + self.tree[index*2+1]
build(0, len(self.nums)-1, 1)
def get_sum(self, i, j):
def get_sum(left_boundary, right_boundary, index, i, j):
if j < i:
return 0
if left_boundary == right_boundary:
return self.tree[index]
if left_boundary == i and right_boundary == j:
return self.tree[index]
else:
mid = (left_boundary + right_boundary)//2
left_sum = get_sum(left_boundary, mid, index*2, i, min(j, mid))
right_sum = get_sum(mid+1, right_boundary,
index*2+1, max(i, mid+1), j)
return left_sum + right_sum
return get_sum(0, len(self.nums)-1, 1, i, j)
def update(self, pos, num):
def update(l, r, index):
if l == r and l == pos:
self.tree[index] = num
else:
mid = (l+r)//2
if pos <= mid:
update(l, mid, index*2)
else:
update(mid+1, r, index*2+1)
self.tree[index] = self.tree[index*2] + self.tree[index*2+1]
update(0, len(self.nums)-1, 1)
def main():
n, q = map(int, input().split())
nums = [0] * n
s = SegmentTree(n)
def update(ops):
plus, i, inc = ops.split()
i = int(i)
inc = int(inc)
s.nums[i] += inc
s.update(i, s.nums[i])
def prefix_sum(ops):
q, j = ops.split()
j = int(j)
ans = s.get_sum(0, j-1)
print(ans)
for _ in range(q):
ops = input()
if len(ops.split()) == 3:
update(ops)
else:
prefix_sum(ops)
if __name__ == "__main__":
main()
This sadly times out. How do I optimize it to run faster?