题意:一组数按顺序加入数组,每奇数次加入的时候就输出中位数
如果是求最大最小值,那么我们很容易就会想到利用堆
那么这道题很明显也可以用堆的办法解决——
对顶堆是一种可以O(LOGN)维护在线第K小值的算法思想是维护两个堆,一个小根堆,一个大根堆,保证大根堆中的任意元素小于小根堆,并维护两堆元素数平衡其中一堆堆顶即为中位数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void swap(int &x,int &y){int z=x;x=y;y=z;}
struct small_root_heap{//小根堆
int heap[5010],top;
void insert(int x)//插入
{
heap[++top]=x;
int t=top;
while(t>1&&heap[t]<heap[t>>1])
swap(heap[t],heap[t>>1]),t>>=1;
}
void pop()//弹顶
{
int t=2;
heap[1]=heap[top];heap[top--]=0;
while(t<=top)
{
if(heap[t]>heap[t+1]&&t<top)t++;
if(heap[t]<heap[t>>1])swap(heap[t],heap[t>>1]),t<<=1;
else break;
}
}
}topheap,bottomheap,empty;//两个堆,其中上堆是小根堆,下堆是大根堆
void add(int x)//插入
{
if(x<=-bottomheap.heap[1])bottomheap.insert(-x);
else topheap.insert(x);
//插入,保证下堆的任意元素都小于等于上堆的任意元素
//注意一定要和下堆堆顶比较,因为第一次插入后元素一定在下堆,如果和上堆堆顶比较就会WA
while(topheap.top>bottomheap.top)bottomheap.insert(-topheap.heap[1]),topheap.pop();
while(bottomheap.top>topheap.top+1)topheap.insert(-bottomheap.heap[1]),bottomheap.pop();
//维护上下堆平衡,保证两堆元素数相等或下堆元素数比上堆元素数多1
}
int main()
{
int p,i,j,k,x,m;
scanf("%d",&p);
for(j=1;j<=p;j++)
{
scanf("%d%d",&i,&m);
topheap=bottomheap=empty;
printf("%d %d\n",i,m+1>>1);
for(k=1;k<=m;k++)
{
scanf("%d",&x);add(x);
if(k&1){
printf("%d%c",-bottomheap.heap[1],k==m?'\n':' ');
if(k%20==19)printf("\n");
}
}
}
}