Merge Sort Tree (Smaller or equal elements in given row range) - GeeksforGeeks

22 Apr, 2022
Given an array where each element is a vector containing integers in sorted order. The task is to answer following queries:
count(start, end, k) : Count the numbers smaller than or equal 
                       to k in range from array index 'start'
                       to 'end'.
For convenience we consider an n * n 2-D array where each row corresponds to an integer vector. Examples:
Input : ar[][] = {{2, 4, 5},
                  {3, 4, 9}, 
                  {6, 8, 10}}

        Queries[] = (0, 1, 5)
                    (1, 2, 1)
                    (0, 2, 6)
Output : 5 
         0
         6
Count of elements (smaller than or equal to 5) from
1st row (index 0) to 2nd row (index 1) is 5.
Count of elements (smaller than or equal to 1) from
2nd row to 3nd row is 0
Count of elements (smaller than or equal to 6) from
1st row to 3nd row is 6.
The key idea is to build a Segment Tree with a vector at every node and the vector contains all the elements of the sub-range in a sorted order. And if we observe this segment tree structure this is somewhat similar to the tree formed during the merge sort algorithm(that is why it is called merge sort tree) 
CPP
// C++ program to count number of smaller or// equal to given number and given row range.#include<bits/stdc++.h>using namespace std; const int MAX = 1000; // Constructs a segment tree and stores sTree[]void buildTree(int idx, int ss, int se, vector<int> a[],                                  vector<int> sTree[]){    /*leaf node*/    if (ss == se)    {        sTree[idx] = a[ss];        return;    }     int mid = (ss+se)/2;     /* building left subtree */    buildTree(2*idx+1, ss, mid, a, sTree);     /* building right subtree */    buildTree(2*idx+2, mid+1, se, a, sTree);     /* merging left and right child in sorted order */    merge(sTree[2*idx+1].begin(), sTree[2*idx+1].end(),          sTree[2*idx+2].begin(), sTree[2*idx+2].end(),          back_inserter(sTree[idx]));} // Recursive function to count smaller elements from row// a[ss] to a[se] and value smaller than or equal to k.int queryRec(int node, int start, int end, int ss, int se,         int k, vector<int> a[], vector<int> sTree[]){    /* If out of range return 0 */    if (ss > end || start > se)        return 0;     /* if inside the range return count */    if (ss <= start && se >= end)    {        /* binary search over the sorted vector           to return count >= X */        return upper_bound(sTree[node].begin(),                           sTree[node].end(), k) -                           sTree[node].begin();    }     int mid = (start+end)/2;     /*searching in left subtree*/    int p1 = queryRec(2*node+1, start, mid, ss, se, k, a, sTree);     /*searching in right subtree*/    int p2 = queryRec(2*node+2, mid+1, end, ss, se, k, a, sTree);     /*adding both the result*/    return p1 + p2;} // A wrapper over query().int query(int start, int end, int k, vector<int> a[], int n,                                  vector<int> sTree[]){   return queryRec(0, 0, n-1, start, end, k, a, sTree);} // Driver codeint main(){    int n = 3;    int arr[][3] = { {2, 4, 5},                     {3, 4, 9},                     {6, 8, 10}};     // build an array of vectors from above input    vector<int> a[n];    for (int i=0; i<n; i++)        for (int j=0; j<n; j++)            a[i].push_back(arr[i][j]);     // Construct segment tree    vector<int> sTree[MAX];    buildTree(0, 0, n-1, a, sTree);     /* un-comment to print merge sort tree*/    /*for (int i=0;i<2*n-1;i++)    {        cout << i << "  ";        for (int j=0;j<sTree[i].size();j++)           cout << sTree[i][j]<<" ";        cout << endl;    }*/     //  Answer queries    cout << query(0, 1, 5, a, n, sTree) << endl;    cout << query(1, 2, 1, a, n, sTree) << endl;    cout << query(0, 2, 6, a, n, sTree) << endl;     return 0;}
Output:
5
0
6
buildTree() analysis : Build a merge sort tree takes O(N log N) time which is same as Merge Sort Algorithm. It also takes O(n log n) extra space. query() analysis : A range ‘start’ to ‘end’ can divided into at most Log(n) parts, where we will perform binary search on each part . Binary search requires O(Log n). Therefore total complexity O(Log n * Log n). This article is contributed by Vineet Jha. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
surinderdawra388
array-range-queries
Segment-Tree
Advanced Data Structure
Segment-Tree
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Agents in Artificial Intelligence
Decision Tree Introduction with example
Disjoint Set Data Structures
AVL Tree | Set 2 (Deletion)
Red-Black Tree | Set 2 (Insert)
Insert Operation in B-Tree
Segment Tree | Set 1 (Sum of given range)
Design a Chess Game
Red-Black Tree | Set 3 (Delete)