Description
动态维护中位数问题
Sol
"对顶堆"的在线做法
建立两个二叉堆,一个大根堆一个小根堆
在依次读入这个整数序列的过程中,设当前序列为l,要始终保证:
1.序列中从小到大排名为1~l/2的整数存在大根堆中
2.序列中从小到大排名为l/2+1~l的整数存在小根堆中
每次插入一个数,与之前的中位数相比较,如果较小就插入大根堆,反之..
必须要维护两个堆中的元素数目相差最多为1,否则取出数目多的堆顶加入另一个堆
小根堆的堆顶即为中位数
最后还有来自gql的两点注意qwq:
Code
#include<iostream> #include<cstdio> #include<queue> #define il inline #define Rg register #define go(i,a,b) for(Rg int i=a;i<=b;i++) #define yes(i,a,b) for(Rg int i=a;i>=b;i++) using namespace std; il int read() { int x=0,y=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*y; } int t,t1,n,nw; priority_queue<int>q1; priority_queue<int,vector<int>,greater<int> >q2; int main() { t=read(); while(t--) { t1=read(),n=read();printf("%d %d ",t1,n/2+1); while(q1.size()>0)q1.pop(); while(q2.size()>0)q2.pop(); go(i,1,n) { int x=read(); if(i==1){nw=x;q2.push(x);} else { if(x<nw)q1.push(x); else q2.push(x); } while((int)q1.size()>(int)q2.size()){int y=q1.top();q1.pop();q2.push(y);} if((int)q2.size()-(int)q1.size()>1){int y=q2.top();q2.pop();q1.push(y);} nw=q2.top(); if(i&1)printf("%d ",nw); if((i&1)&&(i/2+1)%10==0)printf(" "); } if((n/2+1)%10)printf(" "); } return 0; }