动态中位数(对顶栈)
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());
}
}

浙公网安备 33010602011771号