$Poj3784\ Running\ Median$

Poj

 

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\n",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("\n");
        }
        if((n/2+1)%10)printf("\n");
    }
    return 0;
}
View Code

 

posted @ 2019-07-24 11:41  DTTTTTTT  阅读(170)  评论(1编辑  收藏  举报