题意:输入M个数,当已输入的个数为奇数个时输出此时的中位数。

一共有M/2+1个中位数要输出,每一行10个。

思路:用两个优先队列,一个是大顶堆,一个小顶堆,大顶堆中存放比中位数小的数,小顶堆中存放比中位数大的数,把第一个数放入大顶堆,如果当前数比上个中位数小就放入大顶堆,否则就就放入小顶堆。当大顶堆比小顶堆多2个元素或者小顶堆比大顶堆多2个元素的时候,就把多的那个顶堆的堆顶放到另一个堆。要求中位数时,如果是奇数时,就是元素多的堆顶,偶数时是两个堆顶的平均数。

代码:

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int kase;
        scanf("%d",&kase);
        int n;
        scanf("%d",&n);
        priority_queue<int>q1;//大顶堆:比中位数小
        priority_queue<int, vector<int>, greater<int> >q2;//小顶堆:比中位数大
        double ls;int cnt=0;
        if(n%2==1)printf("%d %d\n",kase,(n+1)/2);
        else printf("%d %d\n",kase,n/2);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            //printf("(%.1f)\n",ls);
            if(q1.empty()||1.0*x<ls)q1.push(x);
            else q2.push(x);
            if(q1.size()-q2.size()==2)
            {
                //printf("!\n");
                int temp=q1.top();
                q1.pop();
                q2.push(temp);
            }
            else if(q2.size()-q1.size()==2)
            {
                //printf("?\n");
                int temp=q2.top();
                q2.pop();
                q1.push(temp);
            }
            //if(!q1.empty())printf("q1:%d\n",q1.top());
            //if(!q2.empty())printf("q2:%d\n",q2.top());
            if(i%2==1)
            {
                if(q1.size()>q2.size())
                    ls=q1.top(),printf("%d ",q1.top());
                else
                    ls=q2.top(),printf("%d ",q2.top());
                cnt++;
                if(cnt%10==0)printf("\n");
            }
            else ls=(q1.top()+q2.top())/2.0;
        }
        printf("\n");
    }
    return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

CodeForces899D 构造 Previous
补不动的题的一些思想QAQ Next