You can create a simple data structure at the top of the list that stores the start and end range of each increment operation. The start will be 0 in your case, so you can just save the end.
This way, you don’t really have to navigate the list to enlarge it, but you only save that you performed increments on ranges, for example, from {0 to 2} and {from 0 to 3}. In addition, you can also map some operations so that if several operations increase to the same index, you only need to save one record.
In the worst case, this solution is O(q + gx qlogq + n) , where g is the number of get operations, q is the number of updates, and n is the length of the list. Since we can have no more than n different ends for intervals, this reduces to O(q + nlogn + n) = O(q + nlogn) . A naive solution using an update for each request would be O(q * l ), where l (request length) can be up to size n, giving O(q * n) . Therefore, we can expect this solution to be better if q > log n .
The following is an example of a working python:
def RangeStructure(object): def __init__(self, l): self.ranges = collections.defaultdict(int) self.l = l def incToPosition(self, k): self.ranges[k] += 1 def get(self): res = self.l sorted_keys = sorted(self.ranges) last = len(sorted_keys) - 1 to_add = 0 while last >= 0: start = 0 if last < 1 else sorted_keys[last - 1] end = sorted_keys[last] to_add += self.ranges[end] for i in range(start, end): res[i] += to_add last -= 1 return res rs = RangeStructure([10, 20, 30, 40, 50, 60]) rs.incToPosition(2) rs.incToPosition(2) rs.incToPosition(3) rs.incToPosition(4) print rs.get()
And the explanation:
after the ranges of operations will contain (start, end, Inc.) tuples of the form (0, 2, 2), (0, 3, 1), (0, 4, 1); they will be represented in the dict as {2: 2, 3: 1, 4: 1}, since the beginning is always 1 and can be omitted
during the get operation, we guarantee that we will only work with one element of the list once; we sort the ranges in ascending order of their endpoint and move them in reverse order, updating the contained list items and the sum ( to_add ) added to subsequent ranges
Prints as expected:
[14, 24, 32, 41, 50, 60]
source share