题目描述
给出一个长度为 NNN 的非负整数序列 AiA_iAi ,对于所有 1≤k≤(N+1)/21 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2 ,输出 A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1,A3,…,A2k−1 的中位数。即前 1,3,5,…1,3,5,…1,3,5,… 个数的中位数。
输入输出格式
输入格式:第 111 行为一个正整数 NNN ,表示了序列长度。
第 222 行包含 NNN 个非负整数 Ai(Ai≤109)A_i (A_i ≤ 10^9)Ai(Ai≤109) 。
输出格式:共 (N+1)/2(N + 1) / 2(N+1)/2 行,第 iii 行为 A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1,A3,…,A2k−1 的中位数。
输入输出样例
说明
对于 20%20\%20% 的数据, N≤100N ≤ 100N≤100 ;
对于 40%40\%40% 的数据, N≤3000N ≤ 3000N≤3000 ;
对于 100%100\%100% 的数据, N≤100000N ≤ 100000N≤100000 。
分析;
思维比较巧妙
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;
}