中位数 (优先队列)

中位数

这种题型比较常见,所以总结下来为妙。

一般暴力的方法是找到排一个序,然后输出中间点。
然后正解的方法是优先队列。

解法

一个大根堆一个小根堆,用于存储中位数左边的数和中位数右边的数。
然后每一次插入某个数的时候,可以插入到中间,然后判断左右两个堆的大小,保持均等即可。

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
void read(int &x) {
    int f=1;
    x=0;
    char s=getchar();
    while(s<'0'||s>'9') {
        if(s=='-') f=-1;
        s=getchar();
    }
    while(s>='0'&&s<='9') {
        x=x*10+s-'0';
        s=getchar();
    }
    x*=f;
}
int n,m;
int a[200000];
string mid="mid";
string add="add";
priority_queue<int,vector<int>,less<int> >B;
priority_queue<int,vector<int>,greater<int> >S;
int main() {
    read(n);
    for(int i=1; i<=n; i++) read(a[i]);
    sort(a+1,a+1+n);
    for(int i=1; i<=n/2; i++)
        B.push(a[i]);
    for(int i=n/2+1; i<=n; i++)
        S.push(a[i]);
    read(m);
    while(m--) {
        string s;
        cin >> s;
        if(s==add) {
            int opt;
            read(opt);
            if(opt>B.top())
                S.push(opt);
            else if(opt<S.top()) B.push(opt);
            int tb=B.size(),ts=S.size();
            while(tb-ts>=2) {
                int u=B.top();
                B.pop();
                S.push(u);
                tb=B.size(),ts=S.size();
            }
            while(ts-tb>=2) {
                int u=S.top();
                S.pop();
                B.push(u);
                tb=B.size(),ts=S.size();
            }
        }
        if(s==mid) {
            if(B.size()>=S.size()) printf("%d\n",B.top());
            else printf("%d\n",S.top());
        }
    }
    return 0;
}

例题

3871 中位数

猜你喜欢

转载自www.cnblogs.com/ifmyt/p/9792169.html