Open In App

Count of Subarrays of given Array with median at least X

Given an array arr[]of integers with length N and an integer X, the task is to calculate the number of subarrays with median greater than or equal to the given integer X.

Examples:



Input: N=4, A = [5, 2, 4, 1], X = 4
Output: 7
Explanation: For subarray [5], median is 5. (>= 4)
For subarray [5, 2], median is 5.  (>= 4)
For subarray [5, 2, 4], median is 4. (>= 4)
For subarray [5, 2, 4, 1], median is 4. (>= 4)
For subarray [2, 4], median is 4. (>= 4)
For subarray [4], median is 4. (>= 4)
For subarray [4, 1], median is 4. (>= 4)

Input: N = [3, 7, 2, 0, 1, 5], X = 10
Output: 0
Explanation: There are no subarrays with median greater than or equal to X.



 

Approach:  The problem can be solved based on the following idea.

To find a subarray with median greater or equal to X at least half of the elements should be greater than or equal to X.

Follow the below steps to implement the above idea:

Note: For efficiently calculating the number of elements with a value less than or equal to Y, use policy-based data structures.

Below is the implementation of the above approach:




// C++ code to implement the above approach
 
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <functional>
#include <iostream>
using namespace __gnu_pbds;
using namespace std;
 
// A new data structure defined.
typedef tree<int, null_type, less_equal<int>, rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_set;
 
// Function to find the Number of
// subarrays  with median greater than
// or equal to X.
long long findNumberOfSubarray(int arr[],
                               int n, int X)
{
    // Build new array by comparing it with X
    int new_array[n];
 
    for (int i = 0; i < n; i++) {
        if (arr[i] >= X) {
            new_array[i] = 1;
        }
        else {
            new_array[i] = -1;
        }
    }
 
    // Build new array in which
    // at i-th index, Sum of first i elements
    // are stored
    int pref_sum[n];
    pref_sum[0] = new_array[0];
    for (int i = 1; i < n; i++) {
        pref_sum[i] = pref_sum[i - 1]
                      + new_array[i];
    }
 
    // Store the answer
    // Using long long because
    // it can exceed the storage limit of int
    long long ans = 0;
 
    // For storing already traversed values
    ordered_set s;
    s.insert(0);
 
    // Iterating forwards from 0 to n-1.
    for (int i = 0; i < n; i++) {
        int less_than
            = s.order_of_key(pref_sum[i] + 1);
        ans += less_than;
        s.insert(pref_sum[i]);
    }
 
    return ans;
}
 
// Driver Code
int main()
{
    int N = 4, X = 4;
    int arr[] = { 5, 2, 4, 1 };
 
    // Function call
    long long ans
        = findNumberOfSubarray(arr, N, X);
    cout << ans;
    return 0;
}




// Java code to implement the above approach
 
import java.util.*;
 
class GFG {
    // Function to find the Number of
   // subarrays  with median greater than
  // or equal to X.
    public static int findNumberOfSubarray(int[] arr, int n, int X) {
    int[] newArray = new int[n];
    for (int i = 0; i < n; i++) {
        if (arr[i] >= X) {
            newArray[i] = 1;
        } else {
            newArray[i] = -1;
        }
    }
    // Build new array in which
    // at i-th index, Sum of first i elements
    // are stored
    int[] prefSum = new int[n];
    prefSum[0] = newArray[0];
    for (int i = 1; i < n; i++) {
        prefSum[i] = prefSum[i - 1] + newArray[i];
    }
 
    int ans = 0;
    HashSet<Integer> set = new HashSet<>();
    set.add(0);
    // Iterating forwards from 0 to n-1.
    for (int i = 0; i < n; i++) {
        int lessThan = Collections.binarySearch(new ArrayList<>(set), prefSum[i] + 1);
        if (lessThan < 0) {
            lessThan = -(lessThan + 1);
        }
        if (set.contains(prefSum[i] + 1)) {
            lessThan++;
        }
        ans += lessThan;
        set.add(prefSum[i]);
    }
 
    return ans;
}
// Driver Code
public static void main(String[] args) {
    int N = 4, X = 4;
    int[] arr = {5, 2, 4, 1};
 
    int ans = findNumberOfSubarray(arr, N, X);
    System.out.println(ans);
}
}




# python3 code to implement the above approach
import bisect
 
# Function to find the Number of
# subarrays with median greater than
# or equal to X.
def findNumberOfSubarray(arr, n, X):
 
    # Build new array by comparing it with X
    new_array = [0 for _ in range(n)]
 
    for i in range(0, n):
        if (arr[i] >= X):
            new_array[i] = 1
 
        else:
            new_array[i] = -1
 
    # Build new array in which
    # at i-th index, Sum of first i elements
    # are stored
    pref_sum = [0 for _ in range(n)]
    pref_sum[0] = new_array[0]
    for i in range(1, n):
        pref_sum[i] = pref_sum[i - 1] + new_array[i]
 
    # Store the answer
    # Using long long because
    # it can exceed the storage limit of int
    ans = 0
 
    # For storing already traversed values
    s = set()
    s.add(0)
 
    # Iterating forwards from 0 to n-1.
    for i in range(0, n):
 
        less_than = bisect.bisect_left(
            sorted(s), pref_sum[i]+1, lo=0, hi=len(s))
        if pref_sum[i] + 1 in s:
            less_than += 1
        ans += less_than
        s.add(pref_sum[i])
 
    return ans
 
# Driver Code
if __name__ == "__main__":
 
    N, X = 4, 4
    arr = [5, 2, 4, 1]
 
    # Function call
    ans = findNumberOfSubarray(arr, N, X)
    print(ans)
 
    # This code is contributed by rakeshsahni




// C# code to implement the equivalent of the above Java code
 
using System;
using System.Collections.Generic;
 
class GFG
{
  // Function to find the number of subarrays with
  // median greater than or equal to X
  public static int findNumberOfSubarray(int[] arr, int n, int X)
  {
    // Create a new array where elements >= X are marked
    // as 1 and elements < X are marked as -1
    int[] newArray = new int[n];
    for (int i = 0; i < n; i++)
    {
      if (arr[i] >= X)
      {
        newArray[i] = 1;
      }
      else
      {
        newArray[i] = -1;
      }
    }
 
    // Build a new array where the sum of the first
    // i elements is stored at the i-th index
    int[] prefSum = new int[n];
    prefSum[0] = newArray[0];
    for (int i = 1; i < n; i++)
    {
      prefSum[i] = prefSum[i - 1] + newArray[i];
    }
 
    int ans = 0;
 
    // Store the prefix sum values in a HashSet
    HashSet<int> set = new HashSet<int>();
    set.Add(0);
 
    // Iterate forwards from 0 to n-1
    for (int i = 0; i < n; i++)
    {
      // Find the number of elements less than (prefSum[i] + 1) using binary search
      int lessThan = Array.BinarySearch(new List<int>(set).ToArray(), prefSum[i] + 1);
      if (lessThan < 0)
      {
        lessThan = -(lessThan + 1);
      }
 
      // If (prefSum[i] + 1) is in the set, increment lessThan
      if (set.Contains(prefSum[i] + 1))
      {
        lessThan++;
      }
 
      // Add the number of subarrays ending at i with median >= X
      ans += lessThan;
 
      // Add the current prefix sum value to the set
      set.Add(prefSum[i]);
    }
 
    return ans;
  }
 
  // Driver Code
  static void Main(string[] args)
  {
    int N = 4, X = 4;
    int[] arr = { 5, 2, 4, 1 };
 
    int ans = findNumberOfSubarray(arr, N, X);
    Console.WriteLine(ans);
  }
}




// javascript code to implement the above approach
 
// Function to find the Number of
// subarrays with median greater than
// or equal to X.
function findNumberOfSubarray(arr, n, X) {
 
 
    // Build new array by comparing it with X
    let new_array = Array(n).fill(0);
 
    for (let i = 0; i < n; i++) {
        if (arr[i] >= X) {
            new_array[i] = 1;
        } else {
            new_array[i] = -1;
        }
    }
 
    // Build new array in which
    // at i-th index, Sum of first i elements
    // are stored
    let pref_sum = Array(n).fill(0);
    pref_sum[0] = new_array[0];
    for (let i = 1; i < n; i++) {
        pref_sum[i] = pref_sum[i - 1] + new_array[i];
    }
 
    // Store the answer
    // Using BigInt because it can exceed the storage limit of int
    let ans = BigInt(0);
 
    // For storing already traversed values
    let s = new Set();
    s.add(0);
 
    // Iterating forwards from 0 to n-1.
    for (let i = 0; i < n; i++) {
 
        // less_than = bisect.bisect_left(sorted(s), pref_sum[i]+1, lo=0, hi=len(s))
        let sortedS = Array.from(s).sort(function(a, b) {
            return a - b
        });
        let less_than = bisect_left(sortedS, pref_sum[i] + 1, 0, sortedS.length);
        if (s.has(pref_sum[i] + 1)) {
            less_than += 1;
        }
        ans += BigInt(less_than);
        s.add(pref_sum[i]);
    }
 
    return ans;
 
}
 
// binary search equivalent to Python's bisect.bisect_left
function bisect_left(sortedArr, x, lo, hi) {
    lo = lo || 0;
    hi = hi || sortedArr.length;
    while (lo < hi) {
        let mid = (lo + hi) >>> 1;
        if (sortedArr[mid] < x) {
            lo = mid + 1;
        } else {
            hi = mid;
        }
    }
    return lo;
}
 
// Driver Code
let N = 4,
    X = 4;
let arr = [5, 2, 4, 1];
 
// Function call
let ans = findNumberOfSubarray(arr, N, X);
console.log(ans);
 
// This code is contributed by phasing17

Output
7

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


Article Tags :