中位数 (优先队列)

中位数

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

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

解法

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

#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
",B.top());
			else printf("%d
",S.top());
		}
	}
	return 0;
}

例题

3871 中位数

原文地址:https://www.cnblogs.com/ifmyt/p/9792169.html