Good Subarrays Count Algorithm
Criado em: 17 de janeiro de 2025
Criado em: 17 de janeiro de 2025
An array b
of m
integers is called good if, when it is sorted, b⌊m+12⌋=b⌈m+12⌉
. In other words, b
is good if both of its medians are equal. In particular, ⌊m+12⌋=⌈m+12⌉
when m
is odd, so b
is guaranteed to be good if it has an odd length.
You are given an array a
of n
integers. Calculate the number of good subarrays∗
in a
.
∗
An array x
is a subarray of an array y
if x
can be obtained from y
by the deletion of several (possibly, zero or all) elements from the beginning and several (possibly, zero or all) elements from the end.
Input
Each test contains multiple test cases. The first line contains the number of test cases t
(1≤t≤104
). The description of the test cases follows.
The first line of each test case contains a single integer n
(1≤n≤105
) — the length of the array.
The second line of each test case contains n
integers a1,a2,…,an
(1≤ai≤10
) — the given array.
It is guaranteed that the sum of n
over all test cases does not exceed 105
.
Output
For each test case, output a single integer representing the number of good subarrays in a
.
Example
InputCopy
3
4
1 1 1 1
5
1 10 2 3 3
10
6 3 2 3 5 3 4 2 3 5
OutputCopy
10
11
42
Note
In the first case, every subarray is good since all its elements are equal to 1
.
In the second case, an example of a good subarray is b=[10,2,3,3]
. When it is sorted, b=[2,3,3,10]
, so b⌊4+12⌋=b⌈4+12⌉=b2=b3=3
. Another example would be b=[1,10,2]
. On the other hand, b=[1,10]
is not good as its two medians are 1
and 10
, which are not equal.
solve it by dinary serch in c++ , or BIT
Analysis
We are given an integer array of length , and we want to count the number of good subarrays of . A subarray of length is called good if, after sorting , its two medians coincide. Formally,
Equivalently:
Hence the subarray is good if:
Since each test can have up to (and many test cases, but with total ), an solution is too slow.
Below is a common, efficient strategy once we notice that:
Therefore we can “sum over each candidate ” the number of even-length subarrays in which is a majority. Because no even subarray can be majority for two different values at once, we will not double-count.
Finally, we add
The total number of subarrays of an -element array is
Among these, the number of odd-length subarrays is given by a known closed-form:
You can verify this formula by small cases or by combinatorial arguments.
Let us focus on one candidate value . Define a new array
Let be the prefix sum of , i.e.\
Then for a subarray (1-based indices) of length ,
An even-length subarray (so is even, ) has as a majority element if
Since , the condition is
We must also enforce that is even.
A known trick is to rewrite the inequality in a form suitable for Fenwick/BIT or balanced-binary-search (such as std::map
in C++ or similar). The usual approach:
A simpler “two-scan” method (often used in problems with arrays) might also work here, but one must handle the “length is even” part carefully.
However, because , we only have 10 candidate values. That means we can do the following for each :
Collect the counts for each . Since no even subarray can have two distinct majorities, we can sum those counts without double-counting.
Compute = number of odd-length subarrays =
For each candidate :
Sum up over all . Denote this total by .
The final answer (number of good subarrays) is
You repeat the above per test case.
Below is a (somewhat abbreviated) sketch. The key is to implement the counting step for each . There are various ways to handle “only even-length subarrays”; one common trick is:
One straightforward pattern (among several) is:
Because there are multiple ways to code the details, below is a more “direct” counting approach, using a Fenwick tree keyed by the values of . (If you find the offset arithmetic too fiddly, you can store in an std::map<long long,int>
as you iterate from left to right, and do an order-statistic or cumulative-frequency approach.)
cpp#include <bits/stdc++.h> using namespace std; // Fenwick (BIT) for frequencies of indices/values. struct Fenwick { int N; vector<int> fenw; Fenwick(int n) : N(n), fenw(n+1,0) {} void update(int i,int v){ for(; i<=N; i+=(i & -i)) fenw[i]+=v; } int query(int i){ int s=0; for(; i>0; i-=(i & -i)) s+=fenw[i]; return s; } // query range [1..i] }; // You will also need coordinate compression of d[i] values // if they can be large, so you can store them in Fenwicks. int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while(t--){ int n; cin >> n; vector<int> a(n+1); for(int i=1; i<=n; i++){ cin >> a[i]; } // 1) Count all odd-length subarrays long long totalSub = 1LL*n*(n+1)/2; // # of odd subarrays = floor((n+1)/2)*floor((n+2)/2) long long oddCount = 1LL*((n+1)/2)*((n+2)/2); long long ans = oddCount; // all odd-length are already good // 2) For each x in [1..10], count even-length subarrays that have freq(x)>= (L/2 +1) long long evenMajorityCount = 0; for(int x=1; x<=10; x++){ // Build b[i], prefix p[i] vector<int> b(n+1), p(n+1,0); for(int i=1; i<=n; i++){ b[i] = (a[i]==x ? 1 : 0); p[i] = p[i-1] + b[i]; } // We want to count number of pairs (i,j), i<=j, same parity, s.t. // p[j] - p[i-1] >= ( (j - i + 1)/2 ) + 1. // We'll implement a Fenwicks-based or map-based counting. // [Pseudocode or actual detailed code to do the counting...] // You can store d[i] = 2*p[i] - i in two separate maps: one for i even, one for i odd, // or use a single structure but watch the parity constraints carefully. long long countForX = 0; // ... implement the counting logic ... evenMajorityCount += countForX; } ans += evenMajorityCount; cout << ans << "\n"; } return 0; }
The precise details of the Fenwick or binary-search logic can vary. One simpler approach, since and we only do it 10 times, is to store partial sums in an
std::vector<long long>
, do coordinate-compression for the -values, and then use two Fenwicks (one for odd indices, one for even). As you iterate from 0 to , you look up how many -indices in the Fenwicks satisfywith the additional constraint that and have same parity. Then update Fenwicks with .
However you implement it, the core ideas remain:
That solves the problem in about time overall, which is acceptable for .
This yields a clean solution in C++.