题意:输入若干个数,对第k个输入,如果k为奇数,则输出前k个数的中位数。
思路:用两个堆, 大顶堆和小顶堆。每次输入一个数,如果这个数比当前的中位数大,就存入小顶堆中, 否则就存入大顶堆。然后调整, 小顶堆元素的个数要等于大顶堆的元素个数,或者比其多1。如果小顶堆的元素太多,就塞到大顶堆里,反之亦然。
实际上还可以加上删除中位数操作:只要保证大顶堆的元素=小顶堆的元素或者比小顶堆元素多一即可。这样的数据结构实现了:增加一个元素在log(n)时间内完成,其中n是该数据结构中当前元素的个数。注意:数据结构中允许有重复的元素。(2) 返回当前元素集合的中位数,在常数时间内完成。如果当前元素的个数为偶数,那么返回下中位数(即两个中位数中较小的一个)。(3) 删除中位数,在log(n)时间内完成。
3784代码:
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s));
priority_queue<int> h1;
priority_queue<int,vector<int>,greater<int>> h2;
int T,c,n,len1,len2;
void insert(int x){
int j;
if(!len1 && !len2){
h1.push(x);
len1 ++;
return;
}
if(x <= h1.top()){
if(len1 == len2){
h1.push(x);
len1++;
}else{
h1.push(x);
j = h1.top();
h1.pop();
h2.push(j);
len2++;
}
}else{
if(len1 == len2){
h2.push(x);
j = h2.top();
h2.pop();
h1.push(j);
len1++;
}else{
h2.push(x);
len2++;
}
}
}
int query(){
return h1.top();
}
int main(){
scanf("%d",&T);
while(T--){
int i,x;
while(!h1.empty())
h1.pop();
while (!h2.empty())
h2.pop();
len1 = len2 = 0;
scanf("%d %d",&c,&n);
printf("%d %d\n",c,(n+1)>>1);
c = 19;
for(i = 1;i<=n;i++){
scanf("%d",&x);
insert(x);
if(i&1)
printf("%d ",query());
if(i == c){
printf("\n");
c += 20;
}
}
printf("\n");
}
return 0;
}
3784版本2:手动实现堆,不用stl。并且用结构体将两个堆“封装”。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define INF 0x3fffffff
#define N 10005
struct NewDataStruct{
int *h1,*h2;
int len1,len2;
};
struct NewDataStruct* CreateNewDataStruct(){
struct NewDataStruct *ds = (struct NewDataStruct*)malloc(sizeof(struct NewDataStruct));
ds->h1 = (int*)malloc(N*sizeof(int));
ds->h2 = (int*)malloc(N*sizeof(int));
ds->len1 = ds->len2 = 0;
ds->h1[0] = INF;
ds->h2[0] = -INF;
return ds;
}
void siftDownMin(int *heap, int size) {
int i = 1;
int x = heap[i];
i <<= 1;
while(i<=size){
if(i+1<=size && heap[i+1]<heap[i])
i++;
if(x < heap[i])
break;
heap[i/2] = heap[i];
i <<= 1;
}
heap[i/2] = x;
}
void siftDownMax(int *heap, int size) {
int i = 1;
int x = heap[i];
i <<= 1;
while(i<=size){
if(i+1<=size && heap[i+1]>heap[i])
i++;
if(x > heap[i])
break;
heap[i/2] = heap[i];
i <<= 1;
}
heap[i/2] = x;
}
void siftUpMin(int *heap, int size){
int i,x = heap[size];
i = size;
while(i>=1){
if(heap[i/2] <= x)
break;
heap[i] = heap[i/2];
i >>= 1;
}
heap[i] = x;
}
void siftUpMax(int *heap, int size){
int i,x = heap[size];
i = size;
while(i>=1){
if(heap[i/2] >= x)
break;
heap[i] = heap[i/2];
i >>= 1;
}
heap[i] = x;
}
void addOneNumber(struct NewDataStruct* mf,int x){
if(!mf->len1 && !mf->len2){
mf->h1[++mf->len1] = x;
return;
}
if(mf->len1 == mf->len2){
if(x > mf->h2[1]){
mf->h1[++mf->len1] = mf->h2[1];
siftUpMax(mf->h1, mf->len1);
mf->h2[1] = x;
siftDownMin(mf->h2, mf->len2);
}else{
mf->h1[++mf->len1] = x;
siftUpMax(mf->h1, mf->len1);
}
}else{
if(x>=mf->h1[1]){
mf->h2[++mf->len2] = x;
siftUpMin(mf->h2, mf->len2);
}else{
mf->h2[++mf->len2] = mf->h1[1];
siftUpMin(mf->h2, mf->len2);
mf->h1[1] = x;
siftDownMax(mf->h1, mf->len1);
}
}
}
int findMedianNumber(struct NewDataStruct* mf){
return mf->h1[1];
}
void MedianFinderFree(struct NewDataStruct* mf){
free(mf);
}
int main(){
int T,c,n;
scanf("%d",&T);
while(T--){
int i,x;
struct NewDataStruct* mf = CreateNewDataStruct();
scanf("%d %d",&c,&n);
printf("%d %d\n",c,(n+1)>>1);
c = 19;
for(i = 1;i<=n;i++){
scanf("%d",&x);
addOneNumber(mf, x);
if(i&1)
printf("%d ",findMedianNumber(mf));
if(i == c){
printf("\n");
c += 20;
}
}
printf("\n");
MedianFinderFree(mf);
}
}
如果加上删除:
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s));
priority_queue<int> h1;
priority_queue<int,vector<int>,greater<int>> h2;
int T,c,n,len1,len2;
void insert(int x){
int j;
if(!len1 && !len2){
h1.push(x);
len1 ++;
return;
}
if(x <= h1.top()){
if(len1 == len2){
h1.push(x);
len1++;
}else{
h1.push(x);
j = h1.top();
h1.pop();
h2.push(j);
len2++;
}
}else{
if(len1 == len2){
h2.push(x);
j = h2.top();
h2.pop();
h1.push(j);
len1++;
}else{
h2.push(x);
len2++;
}
}
}
int query(){
return h1.top();
}
void del(){
int j;
if(len1 == len2){
h1.pop();
j = h2.top();
h2.pop();
h1.push(j);
len2--;
}else{
len1--;
h1.pop();
}
}
int main(){
scanf("%d",&T);
while(T--){
int i,x;
char ch;
while(!h1.empty())
h1.pop();
while (!h2.empty())
h2.pop();
len1 = len2 = 0;
scanf("%d",&n);
for(i = 1;i<=n;i++){
getchar();
ch = getchar();
if(ch == 'I'){
scanf("%d",&x);
insert(x);
}else if(ch == 'Q')
printf("%d\n",query());
else
del();
}
}
return 0;
}