神奇的中位数
Description
中位数:n个数中的中位数为将这n个数从小到大排好序后,第位数的值。(
为小于等于x的整数最大的那个)。
现在给定一个空的数组a,然后读入n个数,对于每读入一个数就输出当前数组的中位数是多少。
Input
输入第一行包含一个正整数n(1≤n≤1000000)。
第i+1行包含一个整数。
对于数组的构造如下:
假定第 i−1次读入后输出的答案是lastans,那么第i次读入加入到数组中的数为⨁lastans,即
=lastans⨁
(⨁表示异或,lastans初始为0)。
为了帮助读懂该构造方法请看样例解释。
数据保证0≤≤2×
。
Output
输出包含n行,第i行表示在读入第i个数后当前数组的中位数的值。
Sample Input 1
5 1 2 3 0 1
Sample Output 1
1 1 2 2 2
Hint
优先队列放进去会排好序,默认为大顶堆
//升序队列(小顶堆)
priority_queue <int,vector<int>,greater<int> > q;
//降序队列(大顶堆)
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
实现原理:用大顶堆a装中位数之前的,小顶堆b装中位数之后的,令b的顶部元素为中位数m,每次读入元素时,比m小的就放入a中,大于等于m的就放入b中。当a中元素个数大于b时,将a的堆顶元素弹出作为中位数放入b中,当b.size()-a.size()>2时,即b.size()-a.size()==3时,将b的堆顶元素弹出放入a中,b.top()为新的m.
Plus:当a.size()==b.size()时,中位数在a的顶部!不要漏掉这种情况QWQ
本题代码:
#include<stdio.h>
#include<queue>
using namespace std;
priority_queue<int> a;//默认的大顶堆,优先弹出较大的值
priority_queue<int,vector<int>,greater<int>> b; //小顶堆,值较小的元素在上
int n,tp,x,m;
int main(){
scanf("%d",&n);
scanf("%d",&m);
b.push(m);
printf("%d\n",m);
for(int i=1;i<n;i++){
scanf("%d",&x);
tp=x^m;
if(tp<m)a.push(tp);
else b.push(tp);
if(a.size()>=b.size()){ //注意不要漏掉此处的等号,否则考虑不完整
m=a.top();
a.pop();
b.push(m);
}
else if(b.size()-a.size()==3){
a.push(b.top());
b.pop();
m=b.top();
}
printf("%d\n",m);
}
return 0;
}