问题
I have a number sequence of length N. I will have to do Q operations on this number sequence.
In each operation I will be given three integers P, Q, V with P ≤ Q ≤ N and will subtract V from every iᵗʰ integer, where P ≤ i ≤ Q.
After each operation, I will be given another two integers X, Y with X ≤ Y ≤ N. I will have to answer how many integers between the Xᵗʰ and Yᵗʰ (inclusive) integers are positive.
Q will be around 105. I will have to do all the operations and answer the corresponding queries in around 1/2 seconds.
What algorithm/data structure should I use? And what the procedure will be?
Note : I have a decent knowledge in Segment Trees or Binary Indexed Trees. If your solution involves these data structures, that will be great.
回答1:
Data structure
Use a segment tree with lazy propagation for the data structure.
In each node store:
- Number of positive values in all child nodes
- Smallest positive value of all child nodes (i.e. for children with values -1,3,5,-10 the smallest positive value is 3. We ignore -1 and -10 because they are not positive. )
- Pending value to subtract form this node (initialised to 0)
Update
The procedure for updating a range will be:
- Recursively descend into the segment tree until you find a node that is completely covered by the range
- Modify the pending value for the node
Query
The procedure for answering the query for a range will be:
- Recursively descend into the segment tree until you find a node that is completely covered by the range
- Recursively update the node's properties if the pending value for the node is greater than the minimum positive value
Complexity
As each node can only become negative once, I believe this whole procedure should be O(nlogn+qlogn) where n is the length of the sequence and q is the number of operations.
Example
Suppose we have the array [1,5,-3,4].
We will have segment nodes as follows:
[1,5,-3,4] min positive 1, pending change 0
[1,5] min positive 1, pending change 0
[-3,4] min positive 4, pending change 0
Suppose we wanted to update the whole range with a subtraction of 2, we would change this to:
[1,5,-3,4] min positive 1, pending change 2.
Now, as the pending change is >= the min positive, we need to fix the node by recursively pushing the change down into the left child and the right child.
First the left child would change to:
[1,5] min positive 1, pending change 2
We would then expand this node again and apply the updates to become
[-1,3] min positive 3, pending change 0
Next we would come to the right child which would change to
[-3,4] min positive 4, pending change 2
but no further recursion would be required as pending change < min positive.
Finally the recursion would reach the top level node again. We use the properties of the left and right child to calculate that now the min positive is 2 (from the right child with min 4 and pending 2 giving a result of 4-2=2), and we can reset the pending change to 0 because it has been applied to the children.
回答2:
An easy-to-code data structure is called Segment-tree.
A faster but harder-to-code data structure is called Binary-indexed-tree.
来源:https://stackoverflow.com/questions/18687589/after-subtracting-a-number-from-a-sequence-how-many-of-remaining-numbers-are-po