题目描述
给出一个长度为NN的非负整数序列A_iAi,对于所有1 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A_1, A_1 \sim A_3, …,A_1 \sim A_{2k - 1}A1,A1∼A3,…,A1∼A2k−1的中位数。即前1,3,5,…1,3,5,…个数的中位数。
输入格式
第11行为一个正整数NN,表示了序列长度。
第22行包含NN个非负整数A_i (A_i ≤ 10^9)Ai(Ai≤109)。
输出格式
共(N + 1) / 2(N+1)/2行,第ii行为A_1, A_3, …, A_{2k - 1}A1,A3,…,A2k−1的中位数。
输入输出样例
输入 #1复制
7 1 3 5 7 9 11 6
输出 #1复制
1 3 5 6
说明/提示
对于20\%20%的数据,N ≤ 100N≤100;
对于40\%40%的数据,N ≤ 3000N≤3000;
对于100\%100%的数据,N ≤ 100000N≤100000。
#include<bits/stdc++.h>
using namespace std;
#include<stdio.h>
int main(){
priority_queue<int,vector<int>,less<int> > left;//大顶堆,存放比中位数小的数,堆顶即最大的数存放中位数
priority_queue<int,vector<int>,greater<int> > right;//小顶堆,存放比中位数大的数
//正常情况下大根堆应该比小根堆多存放一个数
int n;//序列长度
scanf("%d",&n);
int a;//序列第一个数
scanf("%d",&a);
left.push(a);
printf("%d\n",left.top());//第一次输出,就是将第一个输入值输出
//先将第一个值输出是因为其与后面的输入格式不同
int t=(n+1)/2-1;//-1即少进行一次循环,因为上面已经完成了第一次输出
while(t--){
int x,y;
scanf("%d%d",&x,&y);//每次读入两个值
if(x<=left.top()){//小于等于中位数,放左边
left.push(x);
}else{//大于中位数,放右边
right.push(x);
}
if(y<=left.top()){//同x
left.push(y);
}else{
right.push(y);
}
//如果左边堆大小-1后仍大于右边堆的大小,说明此次循环中x,y都被放到左边
//将大顶堆堆顶即最大值放到小顶堆,中位数随之改变
if(left.size()-1>right.size()){
int temp=left.top();
left.pop();//pop后面要加()
right.push(temp);
}
//如果右边堆大小大于左边堆大小,说明此次循环中x,y都被放到右边
//将小顶堆堆顶即最小值放到大顶堆
if(right.size()>left.size()){
int temp=right.top();
right.pop();
left.push(temp);
}
printf("%d\n",left.top());
}
}