巧妙运用了2个队列来维护中位数。一个是大根堆,(前1-n/2个数)一个是小根堆(后一半的数)插入每个数时比较大小,再决定插入哪个堆栈里。若是某个堆里的元素个数超过了应有的限制,那么就将其堆顶的元素插到另一个堆里即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn=10005;
int p,n,a[maxn];
priority_queue<int> q1;//大根堆 mid前的
priority_queue<int,vector<int>,greater<int> >q2;//小根堆 mid后的
int main()
{
// freopen("fuck.out","w",stdout);
scanf("%d",&p);
for(int pi=1;pi<=p;pi++)
{
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
int num;
scanf("%d%d",&num,&n);int t=(n+1)/2;
printf("%d %d\n",num,t);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i==1)
{
q2.push(a[i]);
printf("%d ",a[i]);
continue;
}
if(a[i]>=q2.top())
{
q2.push(a[i]);
}
else q1.push(a[i]);
if(q1.size()>i/2)
{
int x=q1.top();q1.pop();
q2.push(x);
}
if(q2.size()>(i-(i/2)))
{
// cout<<"here"<<endl;
int x=q2.top();q2.pop();
q1.push(x);
}
if(i%2==0) continue;
printf("%d ",q2.top());
if(((i+1)/2)%10 == 0) puts("");
else if((n%2==1&&i==n)||(n%2==0&&i==n-1))
puts("");
}
}
return 0;
}
这种做法的好处是每次修改只需要改变顶部的元素,提高了效率。
应用范围:求中间的数或者是有明显的2边的分割?
注意2个数据结构的顶部一定是分割点。(相邻的)