We use cookies to ensure you have the best browsing experience on our website. Please read our cookie policy for more information about how we use cookies.
There is no need to apply the operation to child elements if the target range overlaps the found element's range. So I update the found element and mark it. And if it is necessary to access child elements, the operation of the parent will propagate down.
Second improvement - lazy instantiation of child elements
There is no need to immediately instantiate the entire tree. Some of its nodes may not even be required in special test cases. Otherwise it would take extra time.
Some math
This tree is implemented in such a way that it can be used to solve different tasks by overriding only two methods operationResult and operationNode.
operationNode - the operation to be performed on the node. It can be an addition operation to the current value, an assignment operation, a multiplication operation, and so on. One requirement - the operation must be associative. Operation sum is associative.
operationResult - an operation to get a result on a segment. It can be sum, maximum, minimum, etc. In our problem, this is the operation max. This requirement is obtained due to the peculiarity of the implementation of the tree - lazy propagation.
The cumulative main requirement for these two methods is that they must be distributive. Note that I have written methods, not operations. There is a classic problem for a tree of segments - to increase the value on the segment and get the sum on the segment. The increase operation and the sum operation are not distributive. See for yourself. Incrementing the parent by 3 is not the same as incrementing each child by 3.
If these requirements are taken into account, then any problem that satisfies them can be solved.
P.S. I first solved this problem in python. But this solution worked out in 15 seconds on large test cases. It wasn't enough. Rewriting the solution in C++, the result was obtained in less than a second. According to my calculations, the complexity of this solution is O(M log(N)).
Happy codding!
Cookie support is required to access HackerRank
Seems like cookies are disabled on this browser, please enable them to open this website
Array Manipulation
You are viewing a single comment's thread. Return to all comments →
I implemented the solution using a segment tree!
It wouldn't be easy. I had to improve the familiar segment tree. I want to talk about all the improvements in order. Here is my solution.
Schematically, the structure looks like this.
First improvement - lazy propagation.
There is no need to apply the operation to child elements if the target range overlaps the found element's range. So I update the found element and mark it. And if it is necessary to access child elements, the operation of the parent will propagate down.
Second improvement - lazy instantiation of child elements
There is no need to immediately instantiate the entire tree. Some of its nodes may not even be required in special test cases. Otherwise it would take extra time.
Some math
This tree is implemented in such a way that it can be used to solve different tasks by overriding only two methods
operationResult
andoperationNode
.operationNode
- the operation to be performed on the node. It can be an addition operation to the current value, an assignment operation, a multiplication operation, and so on. One requirement - the operation must be associative. Operationsum
is associative.operationResult
- an operation to get a result on a segment. It can be sum, maximum, minimum, etc. In our problem, this is the operationmax
. This requirement is obtained due to the peculiarity of the implementation of the tree - lazy propagation.The cumulative main requirement for these two methods is that they must be distributive. Note that I have written
methods
, notoperations
. There is a classic problem for a tree of segments - to increase the value on the segment and get the sum on the segment. Theincrease
operation and thesum
operation are not distributive. See for yourself. Incrementing the parent by 3 is not the same as incrementing each child by 3.For this task, it is necessary to make the methods distributive. This is possible if the length of the segment is taken into account. Like this.
Methods are now distributive
If these requirements are taken into account, then any problem that satisfies them can be solved.
P.S. I first solved this problem in python. But this solution worked out in 15 seconds on large test cases. It wasn't enough. Rewriting the solution in C++, the result was obtained in less than a second. According to my calculations, the complexity of this solution is
O(M log(N))
.Happy codding!