from __future__ import print_function 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()