动态维护中位数

暴力

开一个priority_queue push pop , 太慢了

#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这一性质,相互移动堆顶的数字
#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)

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

猜你喜欢

转载自blog.csdn.net/qq_43580151/article/details/89424232