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

• Difficulty Level : Hard
• Last Updated : 11 Jul, 2022

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

Example:

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 Segment 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;``}`

## Java

 `import` `java.util.*;``import` `java.io.*;`` ` `// Java program for the above approach``class` `GFG{`` ` `    ``public` `static` `int` `M = ``100000``;`` ` `    ``// Stores the Segment tree``    ``public` `static` `ArrayList> tree = ``      ``new` `ArrayList>();`` ` `    ``// Function to update Segment tree, the root``    ``// of which contains the length of the LIS``    ``public` `static` `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.get(idx).set(``0``, Math.max(tree.get(idx).get(``0``), length_t));``            ``tree.get(idx).set(``1``, 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.get(``2` `* idx).get(``0``) == tree.get(``2` `* idx + ``1``).get(``0``)) {``            ``tree.set(idx, ``new` `ArrayList(``                ``List.of(tree.get(``2` `* idx).get(``0``), ``                        ``tree.get(``2` `* idx).get(``1``) +``                        ``tree.get(``2` `* idx + ``1``).get(``1``))``            ``));``        ``}`` ` `        ``// If length_t of left > length_t right child``        ``else` `if` `(tree.get(``2` `* idx).get(``0``) > tree.get(``2` `* idx + ``1``).get(``0``)) {``            ``tree.set(idx, ``new` `ArrayList(``                ``List.of(tree.get(``2` `* idx).get(``0``), tree.get(``2` `* idx).get(``1``))``            ``));``        ``}`` ` `        ``// If length_t of left < length_t right child``        ``else` `{``            ``tree.set(idx, ``new` `ArrayList(``                ``List.of(tree.get(``2` `* idx + ``1``).get(``0``), tree.get(``2` `* idx + ``1``).get(``1``))``            ``));``        ``}``    ``}`` ` `    ``// Function to find the LIS length``    ``// and count in the given range``    ``public` `static` `ArrayList 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` `new` `ArrayList(tree.get(idx));``        ``}`` ` `        ``// If intervals are not overlapping``        ``ArrayList temp = ``new` `ArrayList(``            ``List.of(Integer.MIN_VALUE, ``0` `)``        ``);`` ` `        ``if` `(end < query_start || query_end < start) {``            ``return` `new` `ArrayList(temp);``        ``}`` ` `        ``// If intervals are partially overlapping``        ``int` `mid = (start + end) / ``2``;``        ``ArrayList left_child = query(start, mid, ``                                              ``query_start,``                                              ``query_end, ``2` `* idx);``        ``ArrayList 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.get(``0``) > right_child.get(``0``)) {``            ``return` `new` `ArrayList(left_child);``        ``}`` ` `        ``// If length_t of right child is``        ``// greater than length_t of left child``        ``if` `(right_child.get(``0``) > left_child.get(``0``)) {``            ``return` `new` `ArrayList(right_child);``        ``}`` ` `        ``// If length_t of left``        ``// and right child are equal``        ``// return there sum``        ``return` `new` `ArrayList(``            ``List.of(``                ``left_child.get(``0``),``                ``left_child.get(``1``) + right_child.get(``1``)``            ``)``        ``);``    ``}`` ` `    ``// Function to find count``    ``// of LIS in the given array``    ``public` `static` `int` `countLIS(``int` `arr[], ``int` `n)``    ``{``        ``// Generating value-index pair array``        ``ArrayList> pair_array = ``new` `ArrayList>();`` ` `        ``for``(``int` `i = ``0` `; i < n ; i++){``            ``pair_array.add(``new` `ArrayList(``                ``List.of(arr[i], i)``            ``));``        ``}`` ` `        ``// Sort array of pairs with increasing order``        ``// of value and decreasing order of index``        ``Collections.sort(pair_array, ``new` `comp());`` ` `        ``// Traverse the array``        ``// and perform query updates``        ``for` `(``int` `i = ``0` `; i < n ; i++) {`` ` `            ``int` `update_idx = pair_array.get(i).get(``1``);`` ` `            ``// 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]``            ``ArrayList temp = query(``0``, n - ``1``, ``0``, ``                                            ``update_idx - ``1``, ``1``);`` ` `            ``// Update the segment tree``            ``update_tree(``0``, n - ``1``, update_idx, temp.get(``0``) + ``1``, ``                        ``Math.max(``1``, temp.get(``1``)), ``1``);``        ``}`` ` `        ``// Stores the final answer``        ``ArrayList ans = query(``0``, n - ``1``, ``0``, n - ``1``, ``1``);`` ` `        ``// Return answer``        ``return` `ans.get(``1``);``    ``}`` ` ` ` `    ``// Driver code``    ``public` `static` `void` `main(String args[])``    ``{``        ``int` `arr[] = { ``1``, ``3``, ``5``, ``4``, ``7` `};``        ``int` `n = arr.length;`` ` `        ``for``(``int` `i = ``0` `; i < ``4``*M + ``1` `; i++){``            ``tree.add(``new` `ArrayList(``                ``List.of(Integer.MIN_VALUE,``0``)``            ``));``        ``}`` ` `        ``System.out.println(countLIS(arr, n));``    ``}``}`` ` ` ``// Comparator function to sort an array of pairs``// in increasing order of their 1st element and``// thereafter in decreasing order of the 2nd``public` `class` `comp ``implements` `Comparator>{``    ``public` `int` `compare(ArrayList a, ArrayList b)``    ``{``        ``if` `(a.get(``0``).equals(b.get(``0``))) {``            ``return` `b.get(``1``).compareTo(a.get(``1``));``        ``}``        ``return` `a.get(``0``).compareTo(b.get(``0``));``    ``}``}`` ` `// This code is contributed by subhamgoyal2014.`

## Javascript

 ``

Output

`2`

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

Related Topic: Segment Tree

My Personal Notes arrow_drop_up