POJ3784 动态中位数(大根堆+小根堆+优先队列)
Posted karshey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3784 动态中位数(大根堆+小根堆+优先队列)相关的知识,希望对你有一定的参考价值。
题目要求每当输入到奇数个数字时,输出中位数。
我们可以用优先队列来模拟大小根堆,令大根堆放小的数,小根堆放大的数,并且时刻保持大根堆的size大于等于小根堆的,如:当有7个数字时,大根堆4小根堆3;
这样我们就可以保证每次输入奇数的数字时,大根堆.top是中位数,如:
输入1 2 3 4 5 6 7
大根堆:4 3 2 1
小根堆:5 6 7
此时输出的大根堆的top就是中位数。
如果再输入一个8,9,自然都要加入小根堆,于是:
大根堆:4 3 2 1
小根堆:5 6 7 8 9
此时大根堆的size小于小根堆,我们就将小根堆的top放入大根堆,此时:
大根堆:5 4 3 2 1
小根堆:6 7 8 9
这样大根堆的top又是中位数了。
关于用优先队列表示大小根堆:
priority_queue<int,vector<int>,less<int>>;//less表示递减,即从大到小,是大根堆
priority_queue<int,vector<int>,greater<int>>;//greater表示递增,是小根堆
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
#define mem(a,x) memset(a,x,sizeof(a));
#define db double
//大根堆放小的,小根堆放大的
const int N=1e4+10;
int main()
{
int t;scanf("%d",&t);
int cas=0;
while(t--)
{
scanf("%d",&cas);
int m;scanf("%d",&m);
priority_queue<int,vector<int>,less<int>>max_heap;//less递减是大根堆
priority_queue<int,vector<int>,greater<int>>min_heap;//greater是小根堆
printf("%d %d\\n",cas,(m+1)/2);
for(int i=1;i<=m;i++)
{
int tmp;scanf("%d",&tmp);
//放入
if(i==1) max_heap.push(tmp);
else
{
if(tmp<=max_heap.top()) max_heap.push(tmp);
else min_heap.push(tmp);
}
if(min_heap.size()+1<max_heap.size())
{
int tmp2=max_heap.top();
max_heap.pop();
min_heap.push(tmp2);
}
else if(max_heap.size()<min_heap.size())
{
int tmp2=min_heap.top();
min_heap.pop();
max_heap.push(tmp2);
}
if(i%2)
{
printf("%d",max_heap.top());
if(((i+1)/2)%10==0) printf("\\n");
else printf(" ");
}
}
if(((m+1)/2)%10!=0)printf("\\n");
}
return 0;
}
以上是关于POJ3784 动态中位数(大根堆+小根堆+优先队列)的主要内容,如果未能解决你的问题,请参考以下文章