E2. Submedians (Hard Version)
Problem Statement
This is the hard version of the problem. You are asked to find all submedians and for each, any corresponding subarray.
Definition
An integer is a median of an array of length if and only if:
- is greater than or equal to at least elements of the array, and
- is less than or equal to at least elements of the array.
Examples
- The only median of is .
- The medians of are , , and .
- The only median of is .
Task
You’re given an integer and an array of integers between and .
An integer from to is said to be a submedian if there exists at least one pair of indices such that:
- is a median of the subarray
Find all submedians and for each, any corresponding pair of indices .
Input
Each test contains multiple test cases.
The first line contains the number of test cases ().
The description of the test cases follows.
- The first line of each test case contains two integers and ().
- The second line of each test case contains integers ().
It is guaranteed that the sum of over all test cases doesn’t exceed .
Output
For each test case, output your answer in the following format:
- On the first line, output , the number of submedians.
- On the -th of the following lines, output three integers , , and such that and is one of the medians of the subarray .
Each submedian should be reported exactly once, that is, integers must be pairwise distinct. The order in which they are reported does not matter.
If there are many solutions, you can print any of them.
Solution
The hard version of this problem asks for all possible submedians. A key insight is that the set of all submedians forms a contiguous range of integers, [v_min, v_max]. If we can find the minimum possible submedian (v_min) and the maximum possible submedian (v_max), then we can prove that any integer v such that v_min <= v <= v_max is also a submedian.
The overall strategy is therefore:
- Find the maximum submedian,
v_max, and a corresponding subarray[l_max, r_max]. - Find the minimum submedian,
v_min, and a corresponding subarray[l_min, r_min]. - Generate a valid subarray for every integer from
v_mintov_max.
Finding v_max and v_min
Finding v_max is identical to the easy version of the problem. We can use binary search on the answer, x, with the predicate check(x): “Does there exist a subarray where the count of elements >= x is at least the count of elements < x?”. The largest x for which this is true is v_max. This can be solved in .
To find v_min, we can use a clever trick. The minimum value in a set of numbers a is related to the maximum value of the negated set -a. Specifically, min(a) = -max(-a). To avoid dealing with negative numbers, we can use a large constant C and say v_min(a) = C - v_max(C - a). We can apply the same max_mid function to the transformed array a'_i = C - a_i to find v_max(a'). Then, we can find v_min(a) = C - v_max(a'). This also takes .
The Continuity Argument
Now we need to show that every integer between v_min and v_max is a valid submedian. We can do this with a constructive, “continuity” argument. We have a subarray [l_min, r_min] whose median is v_min and another subarray [l_max, r_max] whose median is v_max.
We can transform the first subarray into the second one by applying a series of single-element changes. For example, we can slide the left boundary l_min one step at a time until it reaches l_max, and then do the same for the right boundary. When we add or remove a single element from a subarray, its median value can only change by a small amount. Because the change is gradual, the median of our sliding window will pass through every integer value between v_min and v_max at some point during the transformation. By recording the subarray at each step, we can find a valid window for every submedian in the range.
Implementation: Sliding Window Median
To implement the transformation efficiently, we need a data structure that can maintain the median of a sliding window. A standard and efficient way to do this is with two balanced multisets:
- A
lowmultiset to store the smaller half of the elements in the window. - A
highmultiset to store the larger half of the elements.
We keep the sets balanced so their sizes differ by at most one. With this structure, the median of the window is always at the “join” of the two sets (specifically, it will be the smallest element in high). When an element is added to or removed from the window, we update the multisets and re-balance them. This allows us to find the new median in time, where m is the window size.
The algorithm proceeds as follows:
- Initialize the two multisets with the elements from the
v_minsubarray[l_min, r_min]. - Record all medians from
v_minup to the initial window’s median. - In a loop, apply single-element moves to slide the window from
[l_min, r_min]towards[l_max, r_max]. - After each move, update the multisets, find the new median, and record all integer values between the previous median and the new one, associating them with the current window.
This process constructively finds a valid subarray for every single submedian from v_min to v_max, solving the problem. The complexity of the sliding window part is proportional to the distance between the two subarrays, which is at most , with each step taking , leading to a total complexity dominated by the initial searches.