第一行一个正整数
N
N
N。
第二行
N
N
N 个正整数
A
1
…
N
A_{1\dots N}
A1…N?。
共 ? N + 1 2 ? \lfloor \frac{N + 1}2\rfloor ?2N+1?? 行,第 i i i 行为 A 1 … 2 i ? 1 A_{1\dots 2i - 1} A1…2i?1? 的中位数。
7
1 3 5 7 9 11 6
1
3
5
6
7
3 1 5 9 8 7 6
3
3
5
6
第一次看到这里,首先冒出来的想法是排序(笑死,根本不会 ),先在这里分析一下,我们需要动态地维护,如果先排序再遍历,就会打乱顺序,这题还可以转化为求区间第k大值,看了dalao的题解,秀的天花烂醉,树状数组、权值线段树、主席树、平衡树、二叉排序树、链表······(T-T)
维护两个堆:大顶堆、小顶堆
通俗点就是从中间把大堆切开,左边叫大顶堆,右边叫小顶堆
那么该如何实现呢?
两个堆直接用
p
r
i
o
r
i
t
y
priority
priority_
q
u
e
u
e
queue
queue更方便,大顶堆
Q
1
Q1
Q1,小顶堆
Q
2
Q2
Q2
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,less<int> >Q1;//大顶堆
priority_queue<int,vector<int>,greater<int> >Q2;//小顶堆
int main(){
cin.tie(0)->sync_with_stdio(false);
int n;cin>>n;
for(int i=1,x;i<=n;i++){
cin>>x;
if(i==1) Q2.push(x); //第一个元素进Q2
else{
if(x<Q2.top()) Q1.push(x); //比Q2.top()大,就进Q2
else Q2.push(x);
}
if(i&1){
//维护,使第奇数次,Q2比Q1始终多一个元素
while(Q2.size()-Q1.size()!=1){
if(Q2.size()>Q1.size()) Q1.push(Q2.top()),Q2.pop();
else Q2.push(Q1.top()),Q1.pop();
}
//输出
cout<<Q2.top()<<endl;
}
}
}