前缀中位数
内存限制: 256 Mb时间限制: 1000 ms
题目描述
给定一个整数序列 a1,a2,⋯,an,计算出前一个数,前三个数,前五个数直到前 n 个数的中位数。
所谓一些数的中位数,就是这些数字排序后位置在最中间的数。保证 n 是一个奇数。
输入格式
第一行:单个整数表示 n,保证 n 是奇数;
第二行:n 个整数表示 a1,a2,⋯,an。
输出格式
共 (n−1)/2 行:第 i 行表示前 2i−1 个数字的中位数。
数据范围
- 0≤ai≤10^9;
- 对于 30% 的数据,满足 1≤n≤500;
- 对于 60% 的数据,满足 1≤n≤30,000;
- 对于 100% 的数据,满足1≤n≤100,000。
样例数据
输入:
7
1 3 5 7 9 11 6输出:
1
3
5
6输入:
5
4 3 1 4 2
输出:
4
3
3
解析:
使用对顶堆,保证大顶堆所有数小于等于小顶堆所有数,对于奇数个数,保证大顶堆始终比小顶堆多一个数,大顶堆堆顶即为答案。
详见代码:
#include<bits/stdc++.h>
using namespace std;
int n;
priority_queue <int> d;//大顶堆
priority_queue <int,vector<int>,greater<int>> x;//小顶堆
int main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
int a;
cin>>a;
//将a加入堆内,保证大顶堆的最大数小于小顶堆的最小数
if (d.empty()||a<=d.top()){
d.push(a);
}else{
x.push(a);
}
//对于奇数次
if (i%2==1){
//调整大小顶堆内数字个数,保证大顶堆比小顶堆多一个
if (d.size()-x.size()==3){
int t;
t=d.top();
d.pop();
x.push(t);
}else if(d.size()<x.size()){
int t;
t=x.top();
x.pop();
d.push(t);
}
//大顶堆的堆顶即为中位数
cout<<d.top()<<endl;
}
}
return 0;
}