# Function to build the segment tree
class Node:
def __init__(self):
self.sum = 0
self.prefix = 0
# Function to build the segment tree
def build(arr, ind, start, end, tree):
# if there is only one element
if start == end:
tree[ind].sum = arr[start]
tree[ind].prefix = arr[start]
else:
mid = (start + end) // 2
# If there are more than one elements,
build(arr, 2 * ind + 1, start, mid, tree)
build(arr, 2 * ind + 2, mid + 1, end, tree)
# adds the sum and stores in the
tree[ind].sum = tree[2 * ind + 1].sum + tree[2 * ind + 2].sum
# stores the max of prefix-sum either
tree[ind].prefix = max(tree[2 * ind + 1].prefix, tree[2 * ind + 1].sum + tree[2 * ind + 2].prefix)
# Function to do the range query in the
# segment tree for the maximum prefix sum
def query(ind, start, end, l, r, tree):
result = Node()
result.sum = result.prefix = -1
# If segment of this node is outside the given
# range, then return the minimum value.
if start > r or end < l:
return result
# If segment of this node is a part of given
# range, then return the node of the segment
if start >= l and end <= r:
return tree[ind]
mid = (start + end) // 2
# if left segment of this node falls out of
# range, then recur in the right side of the tree
if l > mid:
return query(2 * ind + 2, mid + 1, end, l, r, tree)
# if right segment of this node falls out of
# range, then recur in the left side of the tree
if r <= mid:
return query(2 * ind + 1, start, mid, l, r, tree)
left = query(2 * ind + 1, start, mid, l, r, tree)
right = query(2 * ind + 2, mid + 1, end, l, r, tree)
# adds the sum of the left and right segment
result.sum = left.sum + right.sum
# stores the max of prefix-sum
result.prefix = max(left.prefix, left.sum + right.prefix)
# returns the value
return result
# Function to return the maximum prefix sum for each query
def maxPrefixes(arr, leftIndex, rightIndex):
n = len(arr)
# to store the segment tree
tree = [Node() for _ in range(4 * n)]
# build the segment tree
build(arr, 0, 0, n - 1, tree)
q = len(leftIndex)
# to store the results
res = []
for i in range(q):
l = leftIndex[i]
r = rightIndex[i]
# query the segment tree
result = query(0, 0, n - 1, l, r, tree)
# store the result
res.append(result.prefix)
return res
if __name__ == "__main__":
arr = [1, -2, 3, 4, -5]
leftIndex = [0, 2, 1]
rightIndex = [4, 3, 3]
res = maxPrefixes(arr, leftIndex, rightIndex)
print(" ".join(map(str, res)))