文章目录
中位数
1.算法分析
1.1 求数组的中位数
1.1.1 sort求中位数
sort。直接sort排序,然后中位数就是a[n / 2],这样的时间复杂度为 O ( n l o g n ) O(nlog_n) O(nlogn)
1.1.2 二分求中位数
二分。二分当前中位数为mid,然后 O ( n ) O(n) O(n)扫一遍数组,然后当前元素a[i]>=mid,记为1,<mid的a[i]为-1。维护前缀和s[i]。如果当前子序列的中位数大于等于x的条件就是它的总和大于0。
1.2 中位数性质
排序不等式: f ( x ) = ∣ x 1 − x ∣ + ∣ x 2 − x ∣ + . . . + ∣ x n − x ∣ f(x) = |x1 - x| + |x2 - x| + ... + |xn - x| f(x)=∣x1−x∣+∣x2−x∣+...+∣xn−x∣的最小值在 x = 中 位 数 x=中位数 x=中位数 时取得。
2.典型例题
2.1 动态维护中位数
acwing106. 动态中位数
题意: 依次读入一个整数序列,每当已经读入的整数个数为奇数时,输出已读入的整数构成的序列的中位数。 1 < = P < = 1000 , 1 < = M < = 9999 1<=P<=1000, 1<=M<=9999 1<=P<=1000,1<=M<=9999
题解: 对顶堆算法。开两个堆,一个是大根堆,一个是小根堆,然后小于中位数的都放在大根堆,大于中位数的都放在小根堆,如果说,一个堆的个数大于了当前序列的1 / 2,那么就将多余的数移过去,直到两个堆数量相等。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &m, &n);
printf("%d %d\n", m, (n + 1) / 2);
priority_queue<int> down;
priority_queue<int, vector<int>, greater<int>> up;
int cnt = 0;
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x