I am solving this problem using segment tree but I get time limit error.
Below is my raw code for range minimum query and by changing min
to max
in my code the above problem can be solved . I don't know how I can improve the performance of my code. Can you help me with its performance issues ?
t = [None] * 2 * 7 # n is length of list
def build(a, v, start, end):
'''
A recursive function that constructs Segment Tree for list a.
v is the starting node
start and end are the index of array
'''
n = len(a)
if start == end:
t[v] = a[start]
else:
mid = (start + end) / 2
build(a, v * 2, start, mid) # v*2 is left child of parent v
# v*2+1 is the right child of parent v
build(a, v * 2 + 1, mid + 1, end)
t[v] = min(t[2 * v], t[2 * v + 1])
return t
print build([18, 17, 13, 19, 15, 11, 20], 1, 0, 6)
inf = 10**9 + 7
def range_minimum_query(node, segx, segy, qx, qy):
'''
returns the minimum number in range(qx,qy)
segx and segy represent the segment index
'''
if qx > segy or qy < segx: # query out of range
return inf
elif segx >= qx and segy <= qy: # query range inside segment range
return t[node]
else:
return min(range_minimum_query(node * 2, segx, (segx + segy) / 2, qx, qy), range_minimum_query(node * 2 + 1, ((segx + segy) / 2) + 1, segy, qx, qy))
print range_minimum_query(1, 1, 7, 1, 3)
# returns 13
Can this be implemented iteratively ?
First, you probably will never pass the grader if you use python. If you look at the status of all past solutions here, http://www.spoj.com/status/GSS1/start=0 , you will see that every almost every accepted solution has been written in C++. I do not think you have a choice but to use C++. Notice how the time limit is 0.115s-0.230s. That's an "only-for-C/C++" time limit. For problems that will accept solutions in other languages, the time limit will be a "round" number like 1 second. Python is about 2-4x slower than C++ in this type of environment.
Second, I'm not sure if your code is actually constructing a segment tree. Specifically, I don't understand why this line is there:
t[v]=min(t[2*v],t[2*v+1])
I'm pretty sure a node in a segment tree stores the sum of its children, so if your implementation is close to correct, I think it should instead read
t[v] = t[2*v] + t[2*v+1]
If your code is "correct", then I would question how you are finding the maximum interval sum within the range [x_i, y_i]
if you don't even store the interval sums.
Third, a segment tree can be implemented iteratively. Here is a tutorial in C++: http://codeforces.com/blog/entry/18051 .
Finally, I don't understand how a segment tree is going to help you for this problem. A segment tree lets you query the sum of a range in log(n)
. This problem asks for the maximum possible sum of any range. I have not heard of a segment tree that allows for "range minimum query" or "range maximum query."
A naive solution will be O(n^3) (try all n^2 possible start and end points and compute the sum in O(n) operations) for 1 query. And, if you use a segment tree, you can get the sum in O(log(n)) instead of O(n). That only speeds you up to O(n^2 log(n)), which cannot work for N = 50000.
I think you should be looking at this instead, which runs in O(n) per query: http://www.geeksforgeeks.org/largest-sum-contiguous-subarray/ . Write it in C/C++ and be efficient with IO as one commenter suggested.