中位数,堆,优先队列

题目描述

给出一个长度为 NNN 的非负整数序列 AiA_iAi ,对于所有 1≤k≤(N+1)/21 ≤ k ≤ (N + 1) / 21k(N+1)/2 ,输出 A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1,A3,,A2k1 的中位数。即前 1,3,5,…1,3,5,…1,3,5, 个数的中位数。

输入输出格式

输入格式:

111 行为一个正整数 NNN ,表示了序列长度。

222 行包含 NNN 个非负整数 Ai(Ai≤109)A_i (A_i ≤ 10^9)Ai(Ai109)

输出格式:

(N+1)/2(N + 1) / 2(N+1)/2 行,第 iii 行为 A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1,A3,,A2k1 的中位数。

输入输出样例

输入样例#1: 复制
7
1 3 5 7 9 11 6
输出样例#1: 复制
1
3
5
6

说明

对于 20%20\%20% 的数据, N≤100N ≤ 100N100

对于 40%40\%40% 的数据, N≤3000N ≤ 3000N3000

对于 100%100\%100% 的数据, N≤100000N ≤ 100000N100000

分析;

思维比较巧妙

1。两个堆,借鉴,max,min;

2。输入第一个数字后,每输入两个数字要输出一次,所以用bool标记,初始为1,从第二个数字开始,每输入一个改变一次;

a1 a2 a3
1 0 1

当bool为真时就意味着要输出了;

3。堆只能输出堆顶的数字,所以要把中位数放在堆顶;

min中从小到大排,优先队列默认从大到小,所以入队时为push(-a);则相当于从小到大;

如果比min中最小的大就放到max中去;

如果两个堆相差2说明较长堆中第二个数是中位数,这时要转移top数到另一个堆,以便输入新数据,得到新中位数;

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int main()
{
    int n,a;
    scanf("%d",&n);
    priority_queue<int>max,min;
    scanf("%d",&a);printf("%d\n",a);
    min.push(-a);
    bool no=1;
    for(int i=1;i<n;i++)
    {
        no=1-no;
        scanf("%d",&a);
        if(a>=-min.top())min.push(-a);else max.push(a);
        if(min.size()-max.size()==2){max.push(-min.top()),min.pop();}
        else if(max.size()-min.size()==2){min.push(-max.top()),max.pop();}
        if(no)
        {
            if(min.size()>max.size())printf("%d\n",-min.top());
            else printf("%d\n",max.top());
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/k42946/article/details/80776099
今日推荐