欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POJ 3784 Running Median【对顶堆】

程序员文章站 2022-03-31 20:02:36
...

传送门
题目大致意思:依次读入一个整数序列,每当读入的整数个数为奇数时,输出已经读入的整数构成的序列的中位数
手写的二叉堆只过了例样,调了半天还是WA
无奈只能投机取巧用stl的优先队列

思路:

POJ 3784 Running Median【对顶堆】

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int main(){
	int T;
	cin>>T;
	while (T--) {
		int Case, M;
		cin >> Case >> M;
		printf("%d %d\n",Case,M&1?(M+1)/2:M/2);
		priority_queue<int> q1;//大根堆 
		priority_queue<int,vector<int>, greater<int> > q2; //小根堆 
		for (int i = 1;i <= M;i++){
				int x;cin>>x;
			    if(q2.empty()||x<=q2.top()) q1.push(x);
    			else q2.push(x);
    			if(q1.size() > q2.size() + 1) { q2.push(q1.top()); q1.pop(); }
    			if(q2.size() > q1.size() ) { q1.push(q2.top()); q2.pop(); }
    			if(i&1){
    				 printf("%d%c",q1.top(),i==M?'\n':' ');
                	 if(i%20==19)printf("\n");
				}
			}
	}
}

还有我发现大根堆,小根堆可以互相逻辑表示。
例如 1 2 3 4 5
在大顶堆依次弹出出为 5 4 3 2 1
如果把例子前置一个负号,放入大根堆 :(-1),(-2),(-3),(-4),(-5)
弹出后在把他们变回来 就相当于小根堆的弹出 1 2 3 4 5
下面的用一种优先队列表示大根堆,和小根堆的AC的代码:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int main(){
	int T;
	cin>>T;
	while (T--) {
		int Case, M;
		cin >> Case >> M;
		printf("%d %d\n",Case,M&1?(M+1)/2:M/2);
		priority_queue<int,vector<int>, greater<int> > q1,q2; //小根堆  大根堆 
		for (int i = 1;i <= M;i++){
				int x;cin>>x;
			    if(q2.empty()||x<=-q2.top()) q2.push(-x);
    			else q1.push(x);
    			if(q1.size() > q2.size()) { q2.push(-q1.top()); q1.pop(); }
    			if(q2.size() > q1.size()+1 ) { q1.push(-q2.top()); q2.pop(); }
    			if(i&1){
    				 printf("%d%c",-q2.top(),i==M?'\n':' ');
                	 if(i%20==19)printf("\n");
				}
			}
	}
}

相关标签:

上一篇: P1631 序列合并

下一篇: 优先级队列