动态维护中位数

暴力

开一个priority_queue push pop ,,,,,,, 太慢了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int maxn=10000;
vector <int> num;
int main() {
// freopen("a.txt","r",stdin);
int time;
scanf("%d",&time);
while ( time-- ) {
priority_queue<int> que;
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++) {
int t;
scanf("%d",&t);
que.push(t);
if( i%2 == 1) {
int len=i/2;
while ( len-- ) num.push_back(que.top()),que.pop();
printf("%d ",que.top());
while ( !num.empty() ) que.push(num.back()),num.pop_back();
}
}
printf("\n");
}
return 0;
}

对顶堆

  • 分别用一个大根堆和小根堆,如序列len=7[1,4]放大根堆,其余放入小根堆
  • len%2 == 1时肯定 两个堆大小差距为1,且大根堆的数<=中位数X,小根堆的数>=x
  • 每次判断数i与中位数maxque.top()的大小,i>x 则加入小堆,同理
  • 维护maxque.size()=minque.size()+1这一性质,相互移动堆顶的数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <queue>
using namespace std;
priority_queue<int> maxque;
priority_queue<int> minque;
int main() {
freopen("a.txt","r",stdin);
int t;
scanf("%d",&t);
while (t--) {
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
if( maxque.empty() ) maxque.push(x);//第一个数先加入大堆
else {
//判断 该数与中位数的大小
if( x>maxque.top() ) minque.push(-x);
else maxque.push(x);
}
while ( maxque.size() < minque.size() ) {//大堆 < 小堆
int temp=minque.top();
minque.pop();
maxque.push(-temp);
}
while ( minque.size() < maxque.size()-1 ) {//小堆 比 大堆不止小1个
int temp=maxque.top();
maxque.pop();
minque.push(-temp);
}
if( i%2 == 1) printf("%d ",maxque.top() );//len为奇数时 输出平均数
}
printf("\n");
while ( !maxque.empty() ) maxque.pop();//清空堆
while ( !minque.empty() ) minque.pop();
}
return 0;
}

离线做法(链表+map)

  • 排序后加入到链表,按输入的逆序删除并且记录中位数,然后逆序输出记录的中位数

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!