# Length of Longest Increasing Subsequences (LIS) using Segment Tree

• Difficulty Level : Hard
• Last Updated : 26 Nov, 2021

Given an array arr[] of size N, the task is to count the number of longest increasing subsequences present in the given array.

Example:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: arr[] = {2, 2, 2, 2, 2}
Output: 5
Explanation: The length of the longest increasing subsequence is 1, i.e. {2}. Therefore, count of longest increasing subsequences of length 1 is 5.

Input: arr[] = {1, 3, 5, 4, 7}
Output: 2
Explanation: The length of the longest increasing subsequence is 4, and there are 2 longest increasing subsequences of length 4, i.e. {1, 3, 4, 7} and {1, 3, 5, 7}.

Approach: An approach to the given problem has been already discussed using dynamic programming in this article.
This article suggests a different approach using segment trees. Follow the below steps to solve the given problem:

• Initialise the segment tree as an array of pairs initially containing pairs of (0, 0), where the 1st element represents the length of LIS and 2nd element represents the count of LIS of current length.
• The 1st element of the segment tree can be calculated similarly to the approach discussed in this article.
• The 2nd element of the segment tree can be calculated using the following steps:
• If cases where the length of left child > length of right child, the parent node becomes equal to the left child as LIS will that be of the left child.
• If cases where the length of left child < length of right child, the parent node becomes equal to the right child as LIS will that be of the right child.
• If cases where the length of left child = length of right child, the parent node becomes equal to the sum of the count of LIS of the left child and the right child.
• The required answer is the 2nd element of the root of the segment tree.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the above approach``#include ``using` `namespace` `std;` `#define M 100000` `// Stores the Segemnt tree``vector > tree(4 * M + 1);` `// Function to update Segment tree, the root``// of which contains the length of the LIS``void` `update_tree(``int` `start, ``int` `end,``                 ``int` `update_idx, ``int` `length_t,``                 ``int` `count_c, ``int` `idx)``{``    ``// If the intervals``    ``// are overlapping completely``    ``if` `(start == end``        ``&& start == update_idx) {``        ``tree[idx].first``            ``= max(tree[idx].first, length_t);``        ``tree[idx].second = count_c;``        ``return``;``    ``}` `    ``// If intervals are not overlapping``    ``if` `(update_idx < start``        ``|| end < update_idx) {``        ``return``;``    ``}` `    ``// If intervals are partially overlapping``    ``int` `mid = (start + end) / 2;` `    ``update_tree(start, mid, update_idx,``                ``length_t, count_c,``                ``2 * idx);``    ``update_tree(mid + 1, end, update_idx,``                ``length_t, count_c,``                ``2 * idx + 1);` `    ``// If length_t of left and``    ``// right child are equal``    ``if` `(tree[2 * idx].first``        ``== tree[2 * idx + 1].first) {``        ``tree[idx].first``            ``= tree[2 * idx].first;``        ``tree[idx].second``            ``= tree[2 * idx].second``              ``+ tree[2 * idx + 1].second;``    ``}` `    ``// If length_t of left > length_t right child``    ``else` `if` `(tree[2 * idx].first``             ``> tree[2 * idx + 1].first) {``        ``tree[idx] = tree[2 * idx];``    ``}` `    ``// If length_t of left < length_t right child``    ``else` `{``        ``tree[idx] = tree[2 * idx + 1];``    ``}``}` `// Function to find the LIS length``// and count in the given range``pair<``int``, ``int``> query(``int` `start, ``int` `end,``                     ``int` `query_start,``                     ``int` `query_end, ``int` `idx)``{``    ``// If the intervals``    ``// are overlapping completely``    ``if` `(query_start <= start``        ``&& end <= query_end) {``        ``return` `tree[idx];``    ``}` `    ``// If intervals are not overlapping``    ``pair<``int``, ``int``> temp({ INT32_MIN, 0 });``    ``if` `(end < query_start``        ``|| query_end < start) {``        ``return` `temp;``    ``}` `    ``// If intervals are partially overlapping``    ``int` `mid = (start + end) / 2;``    ``auto` `left_child``        ``= query(start, mid, query_start,``                ``query_end, 2 * idx);``    ``auto` `right_child``        ``= query(mid + 1, end, query_start,``                ``query_end, 2 * idx + 1);` `    ``// If length_t of left child is greater``    ``// than length_t of right child``    ``if` `(left_child.first > right_child.first) {``        ``return` `left_child;``    ``}` `    ``// If length_t of right child is``    ``// greater than length_t of left child``    ``if` `(right_child.first > left_child.first) {``        ``return` `right_child;``    ``}` `    ``// If length_t of left``    ``// and right child are equal``    ``// return there sum``    ``return` `make_pair(left_child.first,``                     ``left_child.second``                         ``+ right_child.second);``}` `// Comparator function to sort an array of pairs``// in increasing order of their 1st element and``// thereafter in decreasing order of the 2nd``bool` `comp(pair<``int``, ``int``> a, pair<``int``, ``int``> b)``{``    ``if` `(a.first == b.first) {``        ``return` `a.second > b.second;``    ``}``    ``return` `a.first < b.first;``}` `// Function to find count``// of LIS in the given array``int` `countLIS(``int` `arr[], ``int` `n)``{``    ``// Generating value-index pair array``    ``vector > pair_array(n);``    ``for` `(``int` `i = 0; i < n; i++) {``        ``pair_array[i].first = arr[i];``        ``pair_array[i].second = i;``    ``}` `    ``// Sort array of pairs with increasing order``    ``// of value and decreasing order of index``    ``sort(pair_array.begin(),``         ``pair_array.end(), comp);` `    ``// Traverse the array``    ``// and perform query updates``    ``for` `(``int` `i = 0; i < n; i++) {` `        ``int` `update_idx = pair_array[i].second;` `        ``// If update index is the 1st index``        ``if` `(update_idx == 0) {``            ``update_tree(0, n - 1, 0, 1, 1, 1);``            ``continue``;``        ``}` `        ``// Query over the interval [0, update_idx -1]``        ``pair<``int``, ``int``> temp``            ``= query(0, n - 1, 0,``                    ``update_idx - 1, 1);` `        ``// Update the segment tree``        ``update_tree(0, n - 1, update_idx,``                    ``temp.first + 1,``                    ``max(1, temp.second), 1);``    ``}` `    ``// Stores the final answer``    ``pair<``int``, ``int``> ans``        ``= query(0, n - 1, 0, n - 1, 1);` `    ``// Return answer``    ``return` `ans.second;``}` `// Driver Code``int` `main()``{``    ``int` `arr[] = { 1, 3, 5, 4, 7 };``    ``int` `n = ``sizeof``(arr) / ``sizeof``(``int``);` `    ``cout << countLIS(arr, n);` `    ``return` `0;``}`

## Javascript

 ``
Output
`2`

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up