First element greater than or equal to X in prefix sum of N numbers using Binary Lifting

Given an array of N integers and a number X. The task is to find the index of first element which is greater than or equal to X in prefix sums of N numbers.

Examples:

Input: arr[] = { 2, 5, 7, 1, 6, 9, 12, 4, 6 } and x = 8
Output: 2
prefix sum array formed is { 2, 7, 14, 15, 21, 30, 42, 46, 52}, hence 14 is the number whose index is 2

Input: arr[] = { 2, 5, 7, 1, 6, 9, 12, 4, 6 } and x = 30
Output: 5

Approach: The problem can be solved using lower_bound function in Binary search. But in this post, the problem will be solved using Binary-Lifting. In binary lifting, a value is increased (or lifted) by powers of 2, starting with the highest possible power of 2(log(N)) down to the lowest power(0).

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program to find lower_bound of x in
// prefix sums array using binary lifting.
#include <bits/stdc++.h>
using namespace std;
  
// function to make prefix sums array
void MakePreSum(int arr[], int presum[], int n)
{
    presum[0] = arr[0];
    for (int i = 1; i < n; i++)
        presum[i] = presum[i - 1] + arr[i];
}
  
// function to find lower_bound of x in
// prefix sums array using binary lifting.
int BinaryLifting(int presum[], int n, int x)
{
    // intisalize position
    int pos = 0;
  
    // find log to the base 2 value of n.
    int LOGN = log2(n);
  
    // if x less than first number.
    if (x <= presum[0])
        return 0;
  
    // starting from most significant bit.
    for (int i = LOGN; i >= 0; i--) {
  
        // if value at this position less
        // than x then updateposition
        // Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n && 
            presum[pos + (1 << i)] < x) {
            pos += (1 << i);
        }
    }
  
    // +1 because 'pos' will have position
    // of largest value less than 'x'
    return pos + 1;
}
  
// Driver code
int main()
{
    // given array
    int arr[] = { 2, 5, 7, 1, 6, 9, 12, 4, 6 };
  
    // value to find
    int x = 8;
  
    // size of array
    int n = sizeof(arr) / sizeof(arr[0]);
  
    // to store prefix sum
    int presum[n] = { 0 };
  
    // call for prefix sum
    MakePreSum(arr, presum, n);
  
    // fucntion call
    cout << BinaryLifting(presum, n, x);
  
    return 0;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find lower_bound of x in
// prefix sums array using binary lifting.
import java.util.*;
  
class solution
{
  
// function to make prefix sums array
static void MakePreSum(int []arr, int []presum, int n)
{
    presum[0] = arr[0];
    for (int i = 1; i < n; i++)
        presum[i] = presum[i - 1] + arr[i];
}
  
// function to find lower_bound of x in
// prefix sums array using binary lifting.
static int BinaryLifting(int []presum, int n, int x)
{
    // intisalize position
    int pos = 0;
  
    // find log to the base 2 value of n.
    int LOGN = (int)Math.log(n);
  
    // if x less than first number.
    if (x <= presum[0])
        return 0;
  
    // starting from most significant bit.
    for (int i = LOGN; i >= 0; i--) {
  
        // if value at this position less
        // than x then updateposition
        // Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n && 
            presum[pos + (1 << i)] < x) {
            pos += (1 << i);
        }
    }
  
    // +1 because 'pos' will have position
    // of largest value less than 'x'
    return pos + 1;
}
  
// Driver code
public static void main(String args[])
{
    // given array
    int []arr = { 2, 5, 7, 1, 6, 9, 12, 4, 6 };
  
    // value to find
    int x = 8;
  
    // size of array
    int n = arr.length;
  
    // to store prefix sum
    int []presum = new int[n];
    Arrays.fill(presum,0);
  
    // call for prefix sum
    MakePreSum(arr, presum, n);
  
    // fucntion call
    System.out.println(BinaryLifting(presum, n, x));
  
}
  
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 program to find 
# lower_bound of x in prefix 
# sums array using binary lifting.
import math
  
# function to make prefix 
# sums array
def MakePreSum( arr, presum, n):
  
    presum[0] = arr[0]
    for i in range(1, n):
        presum[i] = presum[i - 1] + arr[i]
  
# function to find lower_bound of x in
# prefix sums array using binary lifting.
def BinaryLifting(presum, n, x):
  
    # intisalize position
    pos = 0
  
    # find log to the base 2 
    # value of n.
    LOGN = int(math.log2(n))
  
    # if x less than first number.
    if (x <= presum[0]):
        return 0
  
    # starting from most significant bit.
    for i in range(LOGN, -1, -1) :
  
        # if value at this position less
        # than x then updateposition
        # Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n and
            presum[pos + (1 << i)] < x) :
            pos += (1 << i)
  
    # +1 because 'pos' will have position
    # of largest value less than 'x'
    return pos + 1
  
# Driver code
if __name__ == "__main__":
      
    # given array
    arr = [ 2, 5, 7, 1, 6
            9, 12, 4, 6 ]
  
    # value to find
    x = 8
  
    # size of array
    n = len(arr)
  
    # to store prefix sum
    presum = [0] * n
  
    # call for prefix sum
    MakePreSum(arr, presum, n)
  
    # fucntion call
    print(BinaryLifting(presum, n, x))
  
# This code is contributed
# by ChitraNayal
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find lower_bound of x in
// prefix sums array using binary lifting.
using System;
  
class GFG
{
  
    // function to make prefix sums array
    static void MakePreSum(int []arr, 
                    int []presum, int n)
    {
        presum[0] = arr[0];
        for (int i = 1; i < n; i++)
            presum[i] = presum[i - 1] + arr[i];
    }
  
    // function to find lower_bound of x in
    // prefix sums array using binary lifting.
    static int BinaryLifting(int []presum,
                            int n, int x)
    {
        // intisalize position
        int pos = 0;
  
        // find log to the base 2 value of n.
        int LOGN = (int)Math.Log(n);
  
        // if x less than first number.
        if (x <= presum[0])
            return 0;
  
        // starting from most significant bit.
        for (int i = LOGN; i >= 0; i--)
        {
  
            // if value at this position less
            // than x then updateposition
            // Here (1<<i) is similar to 2^i.
            if (pos + (1 << i) < n && 
                presum[pos + (1 << i)] < x) 
            {
                pos += (1 << i);
            }
        }
  
        // +1 because 'pos' will have position
        // of largest value less than 'x'
        return pos + 1;
    }
  
    // Driver code
    public static void Main()
    {
        // given array
        int []arr = { 2, 5, 7, 1, 6, 9, 12, 4, 6 };
  
        // value to find
        int x = 8;
  
        // size of array
        int n = arr.Length;
  
        // to store prefix sum
        int []presum = new int[n];
  
        // call for prefix sum
        MakePreSum(arr, presum, n);
  
        // fucntion call
        Console.WriteLine(BinaryLifting(presum, n, x));
    }
}
  
// This code has been contributed
// by PrinciRaj1992 
  
chevron_right

Output:
2


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




pawanasipugmailcom

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.





Article Tags :