Maximum sum increasing subsequence
Maximum sum increasing subsequence: Given a sequence of positive numbers , find an increasing subsequence, maximizing the summation of the elements in the subsequence.
In other words, the goal is to find some indices, , , such that
(1) for ,
(2) is maximum over all increasing subsequence of .
One can use dynamic programming to achieve time complexity : let , where , denotes the maximum sum increasing subsequence of which ends at . Then we have the recursion formula
, for and .
The time complexity is as for each , we spend time to compute it.
Is there any faster algorithm to solve this problem? The answer is yes. In the following, we describe an algorithm with time complexity . The algorithm is from here. The key to speed up the algorithm is to compute within time.
We first describe a slow algorithm, then we show how to use balanced binary search tree to improve the time complexity. Let be an array, whose values are all 0 initially. Define to be the rank of in the sorted sequence of . At the end of algorithm, the entry will contain , where , that is, the rank of is in the sorted sequence of .
We now iterate through each element in , and fill up . In iteration, for , we set (note that we might be taking maximum over empty set, and maximum of an empty set is 0 in that case). The value, is the final answer.
Before giving the formal proof, let’s see an example first. Suppose we have the sequence . After sorting, we get the rank of each element as , where is the rank of . One can easily verify this: the rank of , which is 5, is the element in the sorted sequence ; the rank of , which is , is the element in the sorted sequence, and so on.
Initially, the array .
, so we set . So becomes ;
, we compute to be 5, so we set to be , which is 12. So becomes ;
, we compute to be 0, so we set to be . So becomes ;
, we compute to be 0 (the maximum of an empty set is 0), so we set to be . So becomes ;
, we compute to be 2, so we set to be . So becomes .
, we compute to be 12, so we set to be . So becomes .
Hence, the final answer is .
The correctness of the algorithm is now clear: when we compute , the entry , , corresponds to if , that is, appears before in the input sequence; otherwise, although , we have not encountered yet, so the entry is 0, hence they do not affect the value . Therefore, we are effectively computing .
The time complexity of the algorithm, is clearly . But it is easy to see how we can improve the time complexity by using balanced binary search tree now: in the computation , we are repeatedly querying the maximum over the range in the array . We can build a balanced binary search tree for , whose leaves correspond to entries in , for , and the internal node correspond to the maximum value of all the leaves in the subtree rooted at the internal node. For our example, the root of the balanced binary search tree contains the maximum value of , and its left child is in charge of the sub-range , and its right child is in charge of the sub-range , and so on. Each leaf corresponds to a degenerated range , for . Both query and update in a balanced binary search tree is (the tree height), hence the time complexity of the algorithm is .
Naturally, to implement this, we can use Fenwick tree.