Open In App

Number of elements greater than K in the range L to R using Fenwick Tree (Offline queries)

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Prerequisites: Fenwick Tree (Binary Indexed Tree)
Given an array of N numbers, and a number of queries where each query will contain three numbers(l, r and k). The task is to calculate the number of array elements that are greater than K in the subarray[L, R]. 
Examples: 

Input:  n=6                                           
q=2
arr[ ] = { 7, 3, 9, 13, 5, 4 }
Query1: l=1, r=4, k=6
Query2: l=2, r=6, k=8
Output: 3
2
For the first query, [7, 3, 9, 13] represents the
subarray from index 1 till 4, in which there are
3 numbers which are greater than k=6 that are {7, 9, 13}.
For the second query, there are only
two numbers in the query range which
are greater than k.

Naive Approach is to find the answer for each query by simply traversing the array from index l till r and keep adding 1 to the count whenever the array element is greater than k. 

Algorithm:

  1. Initialize the array and its size
  2. Define a function countElements() to count the number of elements greater than k in subarray[l, r]:
    •    Initialize a count variable to 0
    •    Traverse the subarray from index l to r
             If the element at the current index is greater than k, increment the count by 1
    •    Return the count
  3. For each query, get the values of l, r and k
  4. Call the function countElements() for the current query
  5. Print the result returned by the function

Below is the implementation of the approach:

C++




// C++ code for the approach.
 
#include<bits/stdc++.h>
using namespace std;
 
// Function to count number of elements greater than k in subarray[l, r]
int countElements(int arr[], int n, int l, int r, int k) {
    int count = 0;
     
    // Traverse the subarray from index l to r
    for (int i = l; i <= r; i++) {
        if (arr[i] > k) {
            count++;
        }
    }
     
    return count;
}
 
// Driver code
int main() {
      // Input array
    int arr[] = { 7, 3, 9, 13, 5, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
       
      // 1-based indexing
      // Query 1
      int l = 1, r = 4, k = 6;
   
      // Function call
      int ans = countElements(arr, n, l-1, r-1, k);
      cout << ans << endl;
   
      // 1-based indexing
      // Query 2
      l = 2, r = 6, k = 8;
   
    // Function call
    ans = countElements(arr, n, l-1, r-1, k);
    cout << ans << endl;
 
    return 0;
}


Java




// Java code for the approach.
 
import java.util.*;
 
public class GFG {
    // Function to count number of elements greater than k in subarray[l, r]
    public static int countElements(int[] arr, int n, int l, int r, int k) {
        int count = 0;
 
        // Traverse the subarray from index l to r
        for (int i = l; i <= r; i++) {
            if (arr[i] > k) {
                count++;
            }
        }
 
        return count;
    }
 
    // Driver code
    public static void main(String[] args) {
        // Input array
        int[] arr = { 7, 3, 9, 13, 5, 4 };
        int n = arr.length;
 
        // 1-based indexing
        // Query 1
        int l = 1, r = 4, k = 6;
 
        // Function call
        int ans = countElements(arr, n, l-1, r-1, k);
        System.out.println(ans);
 
        // 1-based indexing
        // Query 2
        l = 2; r = 6; k = 8;
 
        // Function call
        ans = countElements(arr, n, l-1, r-1, k);
        System.out.println(ans);
    }
}


Python3




# Function to count the number of elements greater than k in a subarray[l, r]
def count_elements(arr, l, r, k):
    count = 0
     
    # Traverse the subarray from index l to r
    for i in range(l, r + 1):
        if arr[i] > k:
            count += 1
     
    return count
 
# Driver code
if __name__ == "__main__":
    # Input array
    arr = [7, 3, 9, 13, 5, 4]
    n = len(arr)
     
    # 1-based indexing
    # Query 1
    l, r, k = 1, 4, 6
 
    # Function call
    ans = count_elements(arr, l - 1, r - 1, k)
    print(ans)
 
    # 1-based indexing
    # Query 2
    l, r, k = 2, 6, 8
 
    # Function call
    ans = count_elements(arr, l - 1, r - 1, k)
    print(ans)


C#




using System;
 
class GFG {
    // Function to count number of elements greater than k
    // in subarray[l, r]
    static int CountElements(int[] arr, int l, int r, int k)
    {
        int count = 0;
 
        // Traverse the subarray from index l to r
        for (int i = l; i <= r; i++) {
            if (arr[i] > k) {
                count++;
            }
        }
 
        return count;
    }
 
    static void Main(string[] args)
    {
        // Input array
        int[] arr = { 7, 3, 9, 13, 5, 4 };
        int n = arr.Length;
 
        // 1-based indexing
        // Query 1
        int l = 1, r = 4, k = 6;
 
        // Function call
        int ans = CountElements(arr, l - 1, r - 1, k);
        Console.WriteLine(ans);
 
        // 1-based indexing
        // Query 2
        l = 2;
        r = 6;
        k = 8;
 
        // Function call
        ans = CountElements(arr, l - 1, r - 1, k);
        Console.WriteLine(ans);
    }
}


Javascript




// Function to count the number of elements greater than k in a subarray [l, r]
function countElements(arr, l, r, k) {
    let count = 0;
     
    // Traverse the subarray from index l to r
    for (let i = l; i <= r; i++) {
        if (arr[i] > k) {
            count++;
        }
    }
     
    return count;
}
 
// Driver code
// Input array
const arr = [7, 3, 9, 13, 5, 4];
const n = arr.length;
 
// 1-based indexing
// Query 1
const l1 = 1, r1 = 4, k1 = 6;
 
// Function call
const ans1 = countElements(arr, l1 - 1, r1 - 1, k1);
console.log(ans1);
 
// 1-based indexing
// Query 2
const l2 = 2, r2 = 6, k2 = 8;
 
// Function call
const ans2 = countElements(arr, l2 - 1, r2 - 1, k2);
console.log(ans2);


Output

3
2





Time Complexity: O(n*q)
Auxiliary Space: O(1) as no extra space has been used.

A Better Approach is to use Merge Sort Tree. In this approach, build a Segment Tree with a vector at each node containing all the elements of the sub-range in a sorted order. Answer each query using the segment tree where Binary Search can be used to calculate how many numbers are present in each node whose sub-range lies within the query range which are greater than k. 
Time complexity: O(q * log(n) * log(n))
An Efficient Approach is to solve the problem using offline queries and Fenwick Trees. Below are the steps:  

  • First store all the array elements and the queries in the same array. For this, we can create a self-structure or class.
  • Then sort the structural array in descending order ( in case of collision the query will come first then the array element).
  • Process the whole array of structure again, but before that create another BIT array (Binary Indexed Tree) whose query( i ) function will return the count of all the elements which are present in the array till i’th index.
  • Initially, fill the whole array with 0.
  • Create an answer array, in which the answers of each query are stored.
  • Process the array of structure.
  • If it is an array element, then update the BIT array with +1 from the index of that element.
  • If it is a query, then subtract the query(r) – query(l-1) and this will be the answer for that query which will be stored in answer array at the index corresponding to the query number.
  • Finally output the answer array.

The key observation here is that since the array of the structure has been sorted in descending order. Whenever we encounter any query only the elements which are greater than ‘k’ comprises the count in the BIT array which is the answer that is needed. 
Below is the explanation of structure used in the program: 

Pos: stores the order of query. In case of array elements it is kept as 0. 
L: stores the starting index of the query’s subarray. In case of array elements it is also 0. 
R: stores the ending index of the query’s subarray. In case of array element it is used to store the position of element in the array. 
Val: store ‘k’ of the query and all the array elements. 

Below is the implementation of the above approach: 

C++




// C++ program to print the number of elements
// greater than k in a subarray of range L-R.
#include <bits/stdc++.h>
using namespace std;
 
// Structure which will store both
// array elements and queries.
struct node {
    int pos;
    int l;
    int r;
    int val;
};
 
// Boolean comparator that will be used
// for sorting the structural array.
bool comp(node a, node b)
{
    // If 2 values are equal the query will
    // occur first then array element
    if (a.val == b.val)
        return a.l > b.l;
 
    // Otherwise sorted in descending order.
    return a.val > b.val;
}
 
// Updates the node of BIT array by adding
// 1 to it and its ancestors.
void update(int* BIT, int n, int idx)
{
    while (idx <= n) {
        BIT[idx]++;
        idx += idx & (-idx);
    }
}
// Returns the count of numbers of elements
// present from starting till idx.
int query(int* BIT, int idx)
{
    int ans = 0;
    while (idx) {
        ans += BIT[idx];
 
        idx -= idx & (-idx);
    }
    return ans;
}
 
// Function to solve the queries offline
void solveQuery(int arr[], int n, int QueryL[],
                int QueryR[], int QueryK[], int q)
{
    // create node to store the elements
    // and the queries
    node a[n + q + 1];
    // 1-based indexing.
 
    // traverse for all array numbers
    for (int i = 1; i <= n; ++i) {
        a[i].val = arr[i - 1];
        a[i].pos = 0;
        a[i].l = 0;
        a[i].r = i;
    }
 
    // iterate for all queries
    for (int i = n + 1; i <= n + q; ++i) {
        a[i].pos = i - n;
        a[i].val = QueryK[i - n - 1];
        a[i].l = QueryL[i - n - 1];
        a[i].r = QueryR[i - n - 1];
    }
 
    // In-built sort function used to
    // sort node array using comp function.
    sort(a + 1, a + n + q + 1, comp);
 
    // Binary Indexed tree with
    // initially 0 at all places.
    int BIT[n + 1];
 
    // initially 0
    memset(BIT, 0, sizeof(BIT));
 
    // For storing answers for each query( 1-based indexing ).
    int ans[q + 1];
 
    // traverse for numbers and query
    for (int i = 1; i <= n + q; ++i) {
        if (a[i].pos != 0) {
 
            // call function to returns answer for each query
            int cnt = query(BIT, a[i].r) - query(BIT, a[i].l - 1);
 
            // This will ensure that answer of each query
            // are stored in order it was initially asked.
            ans[a[i].pos] = cnt;
        }
        else {
            // a[i].r contains the position of the
            // element in the original array.
            update(BIT, n, a[i].r);
        }
    }
    // Output the answer array
    for (int i = 1; i <= q; ++i) {
        cout << ans[i] << endl;
    }
}
 
// Driver Code
int main()
{
    int arr[] = { 7, 3, 9, 13, 5, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // 1-based indexing
    int QueryL[] = { 1, 2 };
    int QueryR[] = { 4, 6 };
 
    // k for each query
    int QueryK[] = { 6, 8 };
 
    // number of queries
    int q = sizeof(QueryL) / sizeof(QueryL[0]);
 
    // Function call to get
    solveQuery(arr, n, QueryL, QueryR, QueryK, q);
 
    return 0;
}


Java




//Java program to print the number of elements
//greater than k in a subarray of range L-R.
import java.util.*;
//Structure which will store both
//array elements and queries.
public class Main {
static class Node {
    int pos;
    int l;
    int r;
    int val;
     
    public Node() {
        pos = 0;
        l = 0;
        r = 0;
        val = 0;
    }
}
 
//Updates the node of BIT array by adding
//1 to it and its ancestors.
public static void update(int[] BIT, int n, int idx) {
    while (idx <= n) {
        BIT[idx] += 1;
        idx += idx & -idx;
    }
}
 
//Returns the count of numbers of elements
//present from starting till idx.
public static int query(int[] BIT, int idx) {
    int ans = 0;
    while (idx > 0) {
        ans += BIT[idx];
        idx -= idx & -idx;
    }
    return ans;
}
 
//Function to solve the queries offline
public static void solveQuery(int[] arr, int n, int[] QueryL,
                        int[] QueryR, int[] QueryK, int q) {
 
    //Create node to store the elements
    //and the queries
    Node[] a = new Node[n + q + 1];
    for (int i = 0; i < n + q + 1; i++) {
        a[i] = new Node();
    }
 
    //1-based indexing
 
    //Traverse for all array numbers
    for (int i = 1; i <= n; i++) {
        a[i].val = arr[i - 1];
        a[i].pos = 0;
        a[i].l = 0;
        a[i].r = i;
    }
 
    //Iterate for all queries
    for (int i = n + 1; i <= n + q; i++) {
        a[i].pos = i - n;
        a[i].val = QueryK[i - n - 1];
        a[i].l = QueryL[i - n - 1];
        a[i].r = QueryR[i - n - 1];
    }
// In-built sorted function used to
    // sort node array using comp function.
    Arrays.sort(a, 1, n + q + 1, new Comparator<Node>() {
        public int compare(Node o1, Node o2) {
            if (o1.val != o2.val)
                return Integer.compare(o2.val, o1.val);
            return Integer.compare(o1.l, o2.l);
        }
    });
     
    //Binary Indexed tree with
    //initially 0 at all places.
    int[] BIT = new int[n + 1];
 
    //For storing answers for
    //each query( 1-based indexing ).
    int[] ans = new int[q + 1];
 
    //Traverse for numbers and query
    for (int i = 1; i <= n + q; i++) {
        if (a[i].pos != 0) {
 
            //Call function to returns answer for each query
            int cnt = query(BIT, a[i].r) - query(BIT, a[i].l - 1);
 
            //This will ensure that answer of each query
            //are stored in order it was initially asked.
            ans[a[i].pos] = cnt;
        } else {
 
            //a[i].r contains the position of the
            //element in the original array.
            update(BIT, n, a[i].r);
        }
    }
 
    //Output the answer array
    for (int i = 1; i <= q; i++) {
        System.out.println(ans[i]);
    }
}
 
//Driver Code
public static void main (String[] args) {
    int[] arr = {7, 3, 9, 13, 5, 4};
    int n = arr.length;
 
    //1-based indexing
    int[] QueryL = {1, 2};
    int[] QueryR = {4, 6};
 
    //k for each query
    int[] QueryK = {6, 8};
 
    //number of queries
    int q = QueryL.length;
 
    //Function call to get
    solveQuery(arr, n, QueryL, QueryR, QueryK, q);
}}


Python3




# Python program to print the number of elements
# greater than k in a subarray of range L-R.
 
# Structure which will store both
# array elements and queries.
class node:
    def __init__(self):
        self.pos = 0
        self.l = 0
        self.r = 0
        self.val = 0
 
# Updates the node of BIT array by adding
# 1 to it and its ancestors.
def update(BIT: list, n: int, idx: int):
    while idx <= n:
        BIT[idx] += 1
        idx += idx & -idx
 
# Returns the count of numbers of elements
# present from starting till idx.
def query(BIT: list, idx: int) -> int:
    ans = 0
    while idx:
        ans += BIT[idx]
        idx -= idx & -idx
    return ans
 
# Function to solve the queries offline
def solveQuery(arr: list, n: int, QueryL: list,
                QueryR: list, QueryK: list, q: int):
 
    # create node to store the elements
    # and the queries
    a = [0] * (n + q + 1)
    for i in range(n + q + 1):
        a[i] = node()
     
    # 1-based indexing
 
    # traverse for all array numbers
    for i in range(1, n + 1):
        a[i].val = arr[i - 1]
        a[i].pos = 0
        a[i].l = 0
        a[i].r = i
 
    # iterate for all queries
    for i in range(n + 1, n + q + 1):
        a[i].pos = i - n
        a[i].val = QueryK[i - n - 1]
        a[i].l = QueryL[i - n - 1]
        a[i].r = QueryR[i - n - 1]
 
    # In-built sorted function used to
    # sort node array using comp function.
    a = [a[0]] + sorted(a[1:],
        key = lambda k: (k.val, k.l),
        reverse = True)
 
    # Binary Indexed tree with
    # initially 0 at all places.
    BIT = [0] * (n + 1)
 
    # For storing answers for
    # each query( 1-based indexing ).
    ans = [0] * (q + 1)
 
    # traverse for numbers and query
    for i in range(1, n + q + 1):
        if a[i].pos != 0:
 
            # call function to returns answer for each query
            cnt = query(BIT, a[i].r) - query(BIT, a[i].l - 1)
 
            # This will ensure that answer of each query
            # are stored in order it was initially asked.
            ans[a[i].pos] = cnt
        else:
 
            # a[i].r contains the position of the
            # element in the original array.
            update(BIT, n, a[i].r)
 
    # Output the answer array
    for i in range(1, q + 1):
        print(ans[i])
 
# Driver Code
if __name__ == "__main__":
 
    arr = [7, 3, 9, 13, 5, 4]
    n = len(arr)
 
    # 1-based indexing
    QueryL = [1, 2]
    QueryR = [4, 6]
 
    # k for each query
    QueryK = [6, 8]
 
    # number of queries
    q = len(QueryL)
 
    # Function call to get
    solveQuery(arr, n, QueryL, QueryR, QueryK, q)
 
# This code is contributed by
# sanjeev2552


C#




// C# program to print the number of elements
// greater than k in a subarray of range L-R.
using System;
using System.Collections.Generic;
 
// Structure which will store both
// array elements and queries.
struct Node
{
    public int pos;
    public int l;
    public int r;
    public int val;
}
 
class Program {
    // Implementing IComparer for custom sorting
    class NodeComparer : IComparer<Node> {
        public int Compare(Node a, Node b)
        {
            // If 2 values are equal the query will
            // occur first then array element
            if (a.val == b.val)
                return a.l > b.l ? -1 : 1;
 
            // Otherwise sorted in descending order.
            return a.val > b.val ? -1 : 1;
        }
    }
 
    // Updates the node of BIT array by adding
    // 1 to it and its ancestors.
    static void Update(int[] BIT, int n, int idx)
    {
        while (idx <= n) {
            BIT[idx]++;
            idx += idx & (-idx);
        }
    }
 
    // Returns the count of numbers of elements
    // present from starting till idx.
    static int Query(int[] BIT, int idx)
    {
        int ans = 0;
        while (idx > 0) {
            ans += BIT[idx];
            idx -= idx & (-idx);
        }
        return ans;
    }
 
    // Function to solve the queries offline
    static void SolveQuery(int[] arr, int n, int[] QueryL,
                           int[] QueryR, int[] QueryK,
                           int q)
    {
        // create node to store the elements
        // and the queries
        Node[] a = new Node[n + q + 1];
        // 1-based indexing.
 
        // traverse for all array numbers
        for (int i = 1; i <= n; ++i) {
            a[i].val = arr[i - 1];
            a[i].pos = 0;
            a[i].l = 0;
            a[i].r = i;
        }
 
        // iterate for all queries
        for (int i = n + 1; i <= n + q; ++i) {
            a[i].pos = i - n;
            a[i].val = QueryK[i - n - 1];
            a[i].l = QueryL[i - n - 1];
            a[i].r = QueryR[i - n - 1];
        }
 
        // Use custom comparer for sorting
        Array.Sort(a, 1, n + q, new NodeComparer());
 
        // Binary Indexed tree with
        // initially 0 at all places.
        int[] BIT = new int[n + 1];
 
        // initially 0
        Array.Clear(BIT, 0, BIT.Length);
 
        // For storing answers for each query( 1-based
        // indexing ).
        int[] ans = new int[q + 1];
 
        // traverse for numbers and query
        for (int i = 1; i <= n + q; ++i) {
            if (a[i].pos != 0) {
                // call function to return answer for each
                // query
                int cnt = Query(BIT, a[i].r)
                          - Query(BIT, a[i].l - 1);
 
                // This will ensure that the answer of each
                // query is stored in the order it was
                // initially asked.
                ans[a[i].pos] = cnt;
            }
            else {
                // a[i].r contains the position of the
                // element in the original array.
                Update(BIT, n, a[i].r);
            }
        }
 
        // Output the answer array
        for (int i = 1; i <= q; ++i) {
            Console.WriteLine(ans[i]);
        }
    }
 
    // Driver Code
    static void Main()
    {
        int[] arr = { 7, 3, 9, 13, 5, 4 };
        int n = arr.Length;
 
        // 1-based indexing
        int[] QueryL = { 1, 2 };
        int[] QueryR = { 4, 6 };
 
        // k for each query
        int[] QueryK = { 6, 8 };
 
        // number of queries
        int q = QueryL.Length;
 
        // Function call to get
        SolveQuery(arr, n, QueryL, QueryR, QueryK, q);
    }
}


Javascript




// JavaScript program to print the number of elements
// greater than k in a subarray of range L-R.
 
// Structure which will store both
// array elements and queries.
class Node {
    constructor(pos, l, r, val) {
        this.pos = pos;
        this.l = l;
        this.r = r;
        this.val = val;
    }
}
 
// Boolean comparator that will be used
// for sorting the structural array.
function comp(a, b) {
    // If 2 values are equal the query will
    // occur first then array element
    if (a.val === b.val)
        return a.l > b.l;
 
    // Otherwise sorted in descending order.
    return a.val > b.val;
}
 
// Updates the node of BIT array by adding
// 1 to it and its ancestors.
function update(BIT, n, idx) {
    while (idx <= n) {
        BIT[idx]++;
        idx += idx & (-idx);
    }
}
 
// Returns the count of numbers of elements
// present from starting till idx.
function query(BIT, idx) {
    let ans = 0;
    while (idx) {
        ans += BIT[idx];
 
        idx -= idx & (-idx);
    }
    return ans;
}
 
// Function to solve the queries offline
function solveQuery(arr, n, QueryL, QueryR, QueryK, q) {
    // create node to store the elements
    // and the queries
    let a = [];
    // 1-based indexing.
 
    // traverse for all array numbers
    for (let i = 0; i < n; i++) {
        a.push(new Node(0, 0, i + 1, arr[i]));
    }
 
    // iterate for all queries
    for (let i = 0; i < q; i++) {
        a.push(new Node(i + 1, QueryL[i], QueryR[i], QueryK[i]));
    }
 
    // In-built sort function used to
    // sort node array using comp function.
    a.sort(comp);
 
    // Binary Indexed tree with
    // initially 0 at all places.
    let BIT = [];
 
    // initially 0
    for (let i = 0; i <= n; i++) {
        BIT.push(0);
    }
 
    // For storing answers for each query( 1-based indexing ).
    let ans = [];
 
    // traverse for numbers and query
    for (let i = 0; i < a.length; i++) {
        if (a[i].pos !== 0) {
 
            // call function to returns answer for each query
            let cnt = query(BIT, a[i].r) - query(BIT, a[i].l - 1);
 
            // This will ensure that answer of each query
            // are stored in order it was initially asked.
            ans[a[i].pos] = cnt;
        }
// This code is contributed by Shivam Tiwari


Output

3
2





Time Complexity: O(N * log N) where N = (n+q)
What is offline query? 
In some questions, it is hard to answer queries in any random order. So instead of answering each query separately, store all the queries and then order them accordingly to calculate answer for them efficiently. Store all the answers and then output it in the order it was initially given. 
This technique is called Offline Query.
Note: Instead of Fenwick Tree, segment tree can also be used where each node of the segment tree will store the number of elements inserted till that iteration. The update and query functions will change, rest of the implementation will remain same.
Necessary Condition For Offline Query: This technique can be used only when the answer of one query does not depend on the answers of previous queries since after sorting the order of queries may change.
 



Last Updated : 29 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads