Open In App

Order statistic tree using fenwick tree (BIT)

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

Given an array of integers with limited range (0 to 1000000). We need to implement an Order statistic tree using fenwick tree. 
It should support four operations: Insert, Delete, Select and Rank. Here n denotes the size of Fenwick tree and q denotes number of queries. 

Each query should be one of the following 4 operations. 

  • insertElement(x) – Insert element x into Fenwick tree, with O(log n) worst case time complexity
  • deleteElement(x) – Delete element x from fenwick tree, with O(log n) worse case time complexity
  • findKthSmallest(k) – Find the k-th smallest element stored in the tree, with O(log n * log n) worst case time complexity
  • findRank(x) – Find the rank of element x in the tree, i.e. its index in the sorted list of elements of the tree, with O(log n) time complexity

Prerequisite: Binary Indexed Tree or Fenwick Tree
The idea is to create a BIT of size with maximum limit. We insert an element in BIT using it as an index. When we insert an element x, we increment values of all ancestors of x by 1. To delete an element, we decrement values of ancestors by 1. We basically call standard function update() of BIT for both insert and delete. To find rank, we simply call standard function sum() of BIT. To find k-th smallest element, we do binary search in BIT.

C++




// C++ program to find rank of an element
// and k-th smallest element.
#include <bits/stdc++.h>
using namespace std;
 
const int MAX_VAL = 1000001;
 
/* Updates element at index 'i' of BIT. */
void update(int i, int add, vector<int>& BIT)
{
    while (i > 0 && i < BIT.size())
    {
        BIT[i] += add;
        i = i + (i & (-i));
    }
}
 
/* Returns cumulative sum of all elements of
   fenwick tree/BIT from start upto and
   including element at index 'i'. */
int sum(int i, vector<int>& BIT)
{
    int ans = 0;
    while (i > 0)
    {
        ans += BIT[i];
        i = i - (i & (-i));
    }
 
    return ans;
}
 
// Returns lower bound for k in BIT.
int findKthSmallest(int k, vector<int> &BIT)
{
    // Do binary search in BIT[] for given
    // value k.
    int l = 0;
    int h = BIT.size();
    while (l < h)
    {
        int mid = (l + h) / 2;
        if (k <= sum(mid, BIT))
            h = mid;
        else
            l = mid+1;
    }
 
    return l;
}
 
// Insert x into BIT. We basically increment
// rank of all elements greater than x.
void insertElement(int x, vector<int> &BIT)
{
    update(x, 1, BIT);
}
 
// Delete x from BIT. We basically decreases
// rank of all elements greater than x.
void deleteElement(int x, vector<int> &BIT)
{
    update(x, -1, BIT);
}
 
// Returns rank of element. We basically
// return sum of elements from start to
// index x.
int findRank(int x, vector<int> &BIT)
{
    return sum(x, BIT);
}
 
// Driver code
int main()
{
    vector<int> BIT(MAX_VAL);
    insertElement(20, BIT);
    insertElement(50, BIT);
    insertElement(30, BIT);
    insertElement(40, BIT);
 
    cout << "2nd Smallest element is "
     << findKthSmallest(2, BIT) << endl;
 
    cout << "Rank of 40 is "
         << findRank(40, BIT) << endl;
 
    deleteElement(40, BIT);
 
    cout << "Rank of 50 is "
         << findRank(50, BIT) << endl;
 
    return 0;
}


Java




// Java program to find rank of an element
// and k-th smallest element.
import java.util.Arrays;
 
class GFG{
 
static int MAX_VAL = 1000001;
 
// Updates element at index 'i' of BIT
static void update(int i, int add,
                   Integer[] BIT)
{
    while (i > 0 && i < BIT.length)
    {
        BIT[i] += add;
        i = i + (i & (-i));
    }
}
 
// Returns cumulative sum of all elements
// of fenwick tree/BIT from start upto
// and including element at index 'i'.
static int sum(int i, Integer[] BIT)
{
    int ans = 0;
    while (i > 0)
    {
        ans += BIT[i];
        i = i - (i & (-i));
    }
    return ans;
}
 
// Returns lower bound for k in BIT.
static int findKthSmallest(int k,
                           Integer[] BIT)
{
     
    // Do binary search in BIT[]
    // for given value k.
    int l = 0;
    int h = BIT.length;
     
    while (l < h)
    {
        int mid = (l + h) / 2;
        if (k <= sum(mid, BIT))
            h = mid;
        else
            l = mid + 1;
    }
    return l;
}
 
// Insert x into BIT. We basically
// increment rank of all elements
// greater than x.
static void insertElement(int x, Integer[] BIT)
{
    update(x, 1, BIT);
}
 
// Delete x from BIT. We basically
// decreases rank of all elements
// greater than x.
static void deleteElement(int x, Integer[] BIT)
{
    update(x, -1, BIT);
}
 
// Returns rank of element. We basically
// return sum of elements from start to
// index x.
static int findRank(int x, Integer[] BIT)
{
    return sum(x, BIT);
}
 
// Driver code
public static void main(String[] args)
{
    Integer[] BIT = new Integer[MAX_VAL];
      Arrays.fill(BIT, 0);
       
    insertElement(20, BIT);
    insertElement(50, BIT);
    insertElement(30, BIT);
    insertElement(40, BIT);
 
    System.out.println("2nd Smallest element is " +
                        findKthSmallest(2, BIT));
    System.out.println("Rank of 40 is " +
                        findRank(40, BIT));
 
    deleteElement(40, BIT);
     
    System.out.println("Rank of 50 is " +
                        findRank(50, BIT));
}
}
 
// This code is contributed by sanjeev2552


Python3




from typing import List
 
# Maximum value of elements
MAX_VAL = 1000001
 
def update(i: int, add: int, BIT: List[int]) -> None:
    """Updates element at index 'i' of BIT."""
    while i > 0 and i < len(BIT):
        BIT[i] += add
        i = i + (i & (-i))
 
def sum(i: int, BIT: List[int]) -> int:
    """Returns cumulative sum of all elements of fenwick tree/BIT from start upto
       and including element at index 'i'."""
    ans = 0
    while i > 0:
        ans += BIT[i]
        i = i - (i & (-i))
 
    return ans
 
def find_kth_smallest(k: int, BIT: List[int]) -> int:
    """Returns lower bound for k in BIT."""
    # Do binary search in BIT[] for given value k.
    l = 0
    h = len(BIT)
    while l < h:
        mid = (l + h) // 2
        if k <= sum(mid, BIT):
            h = mid
        else:
            l = mid+1
 
    return l
 
def insert_element(x: int, BIT: List[int]) -> None:
    """Insert x into BIT. We basically increment rank of all elements greater than x."""
    update(x, 1, BIT)
 
def delete_element(x: int, BIT: List[int]) -> None:
    """Delete x from BIT. We basically decreases rank of all elements greater than x."""
    update(x, -1, BIT)
 
def find_rank(x: int, BIT: List[int]) -> int:
    """Returns rank of element. We basically return sum of elements from start to index x."""
    return sum(x, BIT)
 
# Driver code
BIT = [0] * MAX_VAL
insert_element(20, BIT)
insert_element(50, BIT)
insert_element(30, BIT)
insert_element(40, BIT)
 
print(f"2nd Smallest element is {find_kth_smallest(2, BIT)}")
 
print(f"Rank of 40 is {find_rank(40, BIT)}")
 
delete_element(40, BIT)
 
print(f"Rank of 50 is {find_rank(50, BIT)}")
 
#This code is contributed by Shivam Tiwari


Javascript




const MAX_VAL = 1000001;
 
function update(i, add, BIT) {
  while (i > 0 && i < BIT.length) {
    BIT[i] += add;
    i = i + (i & (-i));
  }
}
 
function sum(i, BIT) {
  let ans = 0;
  while (i > 0) {
    ans += BIT[i];
    i = i - (i & (-i));
  }
  return ans;
}
 
function findKthSmallest(k, BIT) {
  let l = 0;
  let h = BIT.length;
  while (l < h) {
    let mid = Math.floor((l + h) / 2);
    if (k <= sum(mid, BIT)) {
      h = mid;
    } else {
      l = mid + 1;
    }
  }
  return l;
}
 
function insertElement(x, BIT) {
  update(x, 1, BIT);
}
 
function deleteElement(x, BIT) {
  update(x, -1, BIT);
}
 
function findRank(x, BIT) {
  return sum(x, BIT);
}
 
let BIT = new Array(MAX_VAL).fill(0);
 
insertElement(20, BIT);
insertElement(50, BIT);
insertElement(30, BIT);
insertElement(40, BIT);
 
console.log(`2nd Smallest element is ${findKthSmallest(2, BIT)}`);
console.log(`Rank of 40 is ${findRank(40, BIT)}`);
 
deleteElement(40, BIT);
 
console.log(`Rank of 50 is ${findRank(50, BIT)}`);
// This code is contributed by Shivam Tiwari


C#




using System;
using System.Collections.Generic;
public class GFG{
 const int MAX_VAL = 1000001;
 
    // Updates element at index 'i' of BIT.
    static void Update(int i, int add, int[] BIT)
    {
        while (i > 0 && i < BIT.Length)
        {
            BIT[i] += add;
            i = i + (i & (-i));
        }
    }
 
    // Returns cumulative sum of all elements of BIT from start upto and
    // including element at index 'i'.
    static int Sum(int i, int[] BIT)
    {
        int ans = 0;
        while (i > 0)
        {
            ans += BIT[i];
            i = i - (i & (-i));
        }
 
        return ans;
    }
 
    // Returns lower bound for k in BIT.
    static int FindKthSmallest(int k, int[] BIT)
    {
        // Do binary search in BIT[] for given value k.
        int l = 0;
        int h = BIT.Length;
        while (l < h)
        {
            int mid = (l + h) / 2;
            if (k <= Sum(mid, BIT))
                h = mid;
            else
                l = mid + 1;
        }
 
        return l;
    }
 
    // Insert x into BIT. We basically increment rank of all elements greater than x.
    static void InsertElement(int x, int[] BIT)
    {
        Update(x, 1, BIT);
    }
 
    // Delete x from BIT. We basically decreases rank of all elements greater than x.
    static void DeleteElement(int x, int[] BIT)
    {
        Update(x, -1, BIT);
    }
 
    // Returns rank of element. We basically return sum of elements from start to index x.
    static int FindRank(int x, int[] BIT)
    {
        return Sum(x, BIT);
    }
 
    static void Main(string[] args)
    {
        int[] BIT = new int[MAX_VAL];
        InsertElement(20, BIT);
        InsertElement(50, BIT);
        InsertElement(30, BIT);
        InsertElement(40, BIT);
 
        Console.WriteLine("2nd Smallest element is " + FindKthSmallest(2, BIT));
 
        Console.WriteLine("Rank of 40 is " + FindRank(40, BIT));
 
        DeleteElement(40, BIT);
 
        Console.WriteLine("Rank of 50 is " + FindRank(50, BIT));
    }
}
// This code is contributed by Shivam Tiwari


Output: 

2nd Smallest element is 30
Rank of 40 is 3
Rank of 50 is 3
Time Complexity:- O(log N)
Space Complexity:- O(N) 



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