中位数 (优先队列)
中位数
这种题型比较常见,所以总结下来为妙。
一般暴力的方法是找到排一个序,然后输出中间点。
然后正解的方法是优先队列。
解法
一个大根堆一个小根堆,用于存储中位数左边的数和中位数右边的数。
然后每一次插入某个数的时候,可以插入到中间,然后判断左右两个堆的大小,保持均等即可。
#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;
}