动态中位数(对顶栈)

https://www.acwing.com/problem/content/description/108/

多多君开了一家自助餐厅,为了更好地管理库存,多多君每天需要对之前的客流量数据进行分析,并根据客流量的中位数来制定合理的备货策略。

输入描述
第一行一个整数N,表示餐厅营业总天数(0<n<=200,000)
第二行共N个整数,分别表示第i天的客流量R

输出描述
第一行长度为N,其中第i个值表示前i天客流量的平均值;
第二行长度为N,其中第i个值表示前i天客流量的中位数。

示例输入
5
1 2 3 4 10
示例输出
1 1 2 2 3

就是用大根堆和小跟堆来模拟出来一个排序好的序列

就是动态中位数:
思路:为了动态维护中位数,我们可以建立两个二叉堆:一个小跟堆、一个大根堆。在依次读入这个整数序列的过程中,设当前序列长度为M,我们始终保持:
1.序列中从小到大排名为1-M/2的整数储存在大根堆中
2.序列中从小到大排名为M/2-M的整数储存在小根堆中。
任何时候,如果某一个堆中元素个数过多,打破了这个性质,就取出该堆的堆顶插入到另一个堆。这样一来,序列的中位数就是小根堆的堆顶了。

添加一个元素时:
原则:大的元素往小根堆里面放,小的元素往大根堆里面放,保证A和B的值可以取到中位数,并且规定小根堆比大根堆最多多一个,设新来的元素是x
1、若小根堆为空或者x >= A,则插入到小根堆min_heap中,否则插入到大根堆中
2、维护大根堆和小根堆的数量关系:小根堆比大根堆最多多一个,
若max_heap.size() > min_heap.size() + 1,将小根堆的堆顶元素转移到大根堆中
若min_heap.size() > max_heap.size(),将大根堆的堆顶元素转移到小根堆中
3、获取中位数
就是max_heap.top()

#include<iostream>
#include<algorithm>
#include<set>
#include<queue> 
using namespace std;
const int maxn=1e5+100;
int a[maxn];
int n;
priority_queue<int,vector<int>,less<int>> max_heap;//最大值 
priority_queue<int,vector<int>,greater<int>> min_heap;//最小值 
int mid=0;
int ans[maxn];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(i==1){
			max_heap.push(a[i]);
		}
		else{
			if(a[i]<=max_heap.top()){
				max_heap.push(a[i]);
			}
			else{
				min_heap.push(a[i]); 
			}
		}
		if(min_heap.size()+1<max_heap.size())
		{
			int tmp2=max_heap.top();
			max_heap.pop();
			min_heap.push(tmp2);
		} 
		else if(max_heap.size()<min_heap.size())
		{
			int tmp2=min_heap.top();
			min_heap.pop();
			max_heap.push(tmp2);
		}
		printf("%d ",max_heap.top());
	}
	
}
posted @ 2024-07-01 21:40  lipu123  阅读(47)  评论(0)    收藏  举报