给定长度为 n 的数组 a,找到一个长度至少为 k 的子数组 a[l…r],组成这个子数组的元素的中位数最大。中位数为这个子数组排序后的第
⌊
n
+
1
2
⌋
\lfloor \frac{n+1}{2} \rfloor
⌊2n+1⌋ 个数字。
1
≤
a
i
≤
n
,
1
≤
k
≤
n
≤
2
⋅
1
0
5
1 \leq a_i \leq n, 1 \leq k \leq n \leq 2 \cdot 10^5
1≤ai≤n,1≤k≤n≤2⋅105
思路:
对于本题的中位数,如果子数组长度为偶数,中位数取中间靠左那个,因此,子数组中大于等于中位数的元素的一定占所有元素的一半以上,即大于等于中位数的元素个数比小于中位数的多,利用这一点,我们可以在
O
(
n
)
\mathcal{O}(n)
O(n) 的时间判断出一个数 x 是否小于等于中位数,若 x 小于等于中位数,则大于等于 x 的数多于小于 x 的数。由上述的判断过程来看,x 的值是有单调性的,即 x 越大,上述 “大于等于 x 的数多于小于 x 的数” 这个条件越不好满足,如果一个数字满足这个条件了,那么比它小的也一定满足,所以当一个数字满足,我们尝试增大这个数字看它是不是也满足,这样 x 就存在一个最大值,因此可以进行二分答案,直到 x 为最大的那个值。
为了实现上述操作,check时我们可以令大于等于 x 的数为 1,小于 x 的数为 -1,这样如果一个区间的和大于 0,就表示满足 “大于等于 x 的数多于小于 x 的数” 这个条件。我们可以计算一个前缀和,并维护
0
,
1
,
.
.
.
,
i
−
k
0, 1, ..., i - k
0,1,...,i−k 位置的最小前缀和 mn,如果当前位置 i 的前缀和 pre[i] 满足 pre[i] - mn > 0,就表示有一段长度大于等于 k 的子数组满足条件。