给定数组的子数组计数,中位数至少为 X
给定一个长度为N的整数数组arr[]和一个整数X ,任务是计算中位数大于或等于给定整数X的子数组的数量。
例子:
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.
方法:可以根据以下思路解决问题。
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.
按照以下步骤实现上述想法:
- 如果数组的每个元素大于或等于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)