📌  相关文章
📜  给定数组的子数组计数,中位数至少为 X

📅  最后修改于: 2022-05-13 01:56:06.589000             🧑  作者: Mango

给定数组的子数组计数,中位数至少为 X

给定一个长度为N的整数数组arr[]和一个整数X ,任务是计算中位数大于或等于给定整数X的子数组的数量。

例子:

方法:可以根据以下思路解决问题。

按照以下步骤实现上述想法:

  • 如果数组的每个元素大于或等于X ,则将其替换为1 ,否则将其替换为-1
  • 基于上述思路,对于新数组,任何子数组的中位数要大于等于X ,其元素之和就应该大于等于 0。
  • 用于计算总和大于或等于 0 的子数组的数量:
    • 查找新数组的每个索引的前缀总和
    • 从索引1开始遍历新创建的前缀数组,并计算它之前的值小于或等于当前值的元素个数。
    • 将所有这些添加到最终答案中,因为它们还将形成一个子数组,当前的子数组满足所有条件。
    • 在为索引找到它之后,将当前值添加到multiset
  • 返回最终答案。

注意:为了有效地计算值小于或等于Y的元素数量,请使用基于策略的数据结构。

下面是上述方法的实现:

C++
// C++ code to implement the above approach
 
#include 
#include 
#include 
#include 
using namespace __gnu_pbds;
using namespace std;
 
// A new data structure defined.
typedef tree, rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_set;
 
// Function to 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;
}


Python3
# python3 code to implement the above approach
import bisect
 
# Function to 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


输出
7

时间复杂度: O(N * logN)
辅助空间: O(N)