题意:一组数按顺序加入数组,每奇数次加入的时候就输出中位数
如果是求最大最小值,那么我们很容易就会想到利用堆
那么这道题很明显也可以用堆的办法解决——
对顶堆是一种可以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"); } } } }
POJ 3784 Running Median 对顶堆算法
最新推荐文章于 2024-07-04 06:51:42 发布