Skip to content

Lazy Segment Tree #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions data_structures/Binary Tree/FenwickTree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class FenwickTree:

def __init__(self, SIZE): # create fenwick tree with size SIZE
self.Size = SIZE
self.ft = [0 for i in range (0,SIZE)]

def update(self, i, val): # update data (adding) in index i in O(lg N)
while (i < self.Size):
self.ft[i] += val
i += i & (-i)

def query(self, i): # query cumulative data from index 0 to i in O(lg N)
ret = 0
while (i > 0):
ret += self.ft[i]
i -= i & (-i)
return ret

if __name__ == '__main__':
f = FenwickTree(100)
f.update(1,20)
f.update(4,4)
print (f.query(1))
print (f.query(3))
print (f.query(4))
f.update(2,-5)
print (f.query(1))
print (f.query(3))
90 changes: 90 additions & 0 deletions data_structures/Binary Tree/LazySegmentTree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import math

class SegmentTree:

def __init__(self, N):
self.N = N
self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N
self.lazy = [0 for i in range(0,4*N)] # create array to store lazy update
self.flag = [0 for i in range(0,4*N)] # flag for lazy update

def left(self, idx):
return idx*2

def right(self, idx):
return idx*2 + 1

def build(self, idx, l, r, A):
if l==r:
self.st[idx] = A[l-1]
else :
mid = (l+r)//2
self.build(self.left(idx),l,mid, A)
self.build(self.right(idx),mid+1,r, A)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])

# update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) for each update)
def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b]
if self.flag[idx] == True:
self.st[idx] = self.lazy[idx]
self.flag[idx] = False
if l!=r:
self.lazy[self.left(idx)] = self.lazy[idx]
self.lazy[self.right(idx)] = self.lazy[idx]
self.flag[self.left(idx)] = True
self.flag[self.right(idx)] = True

if r < a or l > b:
return True
if l >= a and r <= b :
self.st[idx] = val
if l!=r:
self.lazy[self.left(idx)] = val
self.lazy[self.right(idx)] = val
self.flag[self.left(idx)] = True
self.flag[self.right(idx)] = True
return True
mid = (l+r)//2
self.update(self.left(idx),l,mid,a,b,val)
self.update(self.right(idx),mid+1,r,a,b,val)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
return True

# query with O(lg N)
def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b]
if self.flag[idx] == True:
self.st[idx] = self.lazy[idx]
self.flag[idx] = False
if l != r:
self.lazy[self.left(idx)] = self.lazy[idx]
self.lazy[self.right(idx)] = self.lazy[idx]
self.flag[self.left(idx)] = True
self.flag[self.right(idx)] = True
if r < a or l > b:
return -math.inf
if l >= a and r <= b:
return self.st[idx]
mid = (l+r)//2
q1 = self.query(self.left(idx),l,mid,a,b)
q2 = self.query(self.right(idx),mid+1,r,a,b)
return max(q1,q2)

def showData(self):
showList = []
for i in range(1,N+1):
showList += [self.query(1, 1, self.N, i, i)]
print (showList)


if __name__ == '__main__':
A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8]
N = 15
segt = SegmentTree(N)
segt.build(1,1,N,A)
print (segt.query(1,1,N,4,6))
print (segt.query(1,1,N,7,11))
print (segt.query(1,1,N,7,12))
segt.update(1,1,N,1,3,111)
print (segt.query(1,1,N,1,15))
segt.update(1,1,N,7,8,235)
segt.showData()
64 changes: 64 additions & 0 deletions data_structures/Binary Tree/SegmentTree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import math

class SegmentTree:

def __init__(self, N):
self.N = N
self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N

def left(self, idx):
return idx*2

def right(self, idx):
return idx*2 + 1

def build(self, idx, l, r, A):
if l==r:
self.st[idx] = A[l-1]
else :
mid = (l+r)//2
self.build(self.left(idx),l,mid, A)
self.build(self.right(idx),mid+1,r, A)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])

def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b]
if r < a or l > b:
return True
if l == r :
self.st[idx] = val
return True
mid = (l+r)//2
self.update(self.left(idx),l,mid,a,b,val)
self.update(self.right(idx),mid+1,r,a,b,val)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
return True

def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b]
if r < a or l > b:
return -math.inf
if l >= a and r <= b:
return self.st[idx]
mid = (l+r)//2
q1 = self.query(self.left(idx),l,mid,a,b)
q2 = self.query(self.right(idx),mid+1,r,a,b)
return max(q1,q2)

def showData(self):
showList = []
for i in range(1,N+1):
showList += [self.query(1, 1, self.N, i, i)]
print (showList)


if __name__ == '__main__':
A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8]
N = 15
segt = SegmentTree(N)
segt.build(1,1,N,A)
print (segt.query(1,1,N,4,6))
print (segt.query(1,1,N,7,11))
print (segt.query(1,1,N,7,12))
segt.update(1,1,N,1,3,111)
print (segt.query(1,1,N,1,15))
segt.update(1,1,N,7,8,235)
segt.showData()