堆的应用

链接:C++中的堆和栈
这篇博客是讲堆的几种定义

题目

洛谷 P3817 中位数

洛谷 P1168 中位数

P1168代码

STL版本

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int n,a1;
priority_queue<int,vector<int> ,greater<int> >minheap;//小根堆 
priority_queue<int>maxheap;//大根堆 
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar();
    return x*w;
}
int main() {
    n=read();a1=read(); 
    printf("%d\n",a1);
    minheap.push(a1);
    for(int i=1; i<=(n-1)/2; i++) {
        int a,b;
        a=read();b=read();
        if(a<minheap.top()) { maxheap.push(a);} else { minheap.push(a);}
        if(b<minheap.top()) { maxheap.push(b);} else { minheap.push(b);}
        while(maxheap.size()>=minheap.size()) { minheap.push(maxheap.top()); maxheap.pop();}
        while(maxheap.size()<minheap.size()-1) {maxheap.push(minheap.top());minheap.pop();}
        printf("%d\n",minheap.top());
    }
    return 0;
}

手动模拟堆(不过有点长)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define fp(i,a,b) for(register int i=a;i<=b;++i)
using namespace std;
int n,t1,t2,size1,size2,mid;
int big[400005],small[400005];
//首先,想想为什么可以用 
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar();
    return x*w;
}
inline void big_put(int x){
    big[++size2]=x;
    int now=size2,next;
    while(now>1){
        next=now>>1;
        if(big[now]<=big[next]) return;
        swap(big[now],big[next]);
        now=next;
    }
}
inline int big_get(){
    int now=1,next,v=big[1];
    big[1]=big[size2--];
    while(now<<1<=size2){
        next=now<<1;
        if(next<size2&&big[next+1]>big[next]) ++next;
        if(big[now]>=big[next]) break;
        swap(big[next],big[now]);
        now=next;
    }
    return v;
}
inline void small_put(int x){
    small[++size1]=x;
    int now=size1,next;
    while(now>1){
        next=now>>1;
        if(small[now]>=small[next]) return;
        swap(small[now],small[next]);
        now=next;
    }
}
inline int small_get(){
    int now=1,next,v=small[1];
    small[1]=small[size1--];
    while(now<<1<=size1){
        next=now<<1;
        if(next<size1&&small[next+1]<small[next]) ++next;
        if(small[now]<=small[next]) break;
        swap(small[next],small[now]);
        now=next;
    }
    return v;
}
int main(){
    n=read();t1=read();
    big_put(t1);printf("%d\n",mid=t1);
    for(register int i=1;i<<1<n;++i){
        t1=read();t2=read();
        if(t1>mid) small_put(t1);else big_put(t1);
        if(t2>mid) small_put(t2);else big_put(t2);
        if(size1>=size2) big_put(small_get());
        if(size1+1<size2) small_put(big_get());
        printf("%d\n",mid=big[1]);
    }
    return 0;
}

P3387代码

STL版本

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int n,m,mid;
char s[10];
priority_queue<int,vector<int> ,greater<int> >minheap;//小根堆 
priority_queue<int>maxheap;//大根堆 
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar();
    return x*w;
}
int main() {
    n=read();
    for(register int i=1; i<=n; ++i) {
        int a;
        a=read();
        if(a>mid) { minheap.push(a);} else { maxheap.push(a);}
        while(minheap.size()>=maxheap.size()) { maxheap.push(minheap.top()); minheap.pop();}
        while(minheap.size()+1<maxheap.size()) {minheap.push(maxheap.top());maxheap.pop();}
    }
    m=read();
    for(register int i=1;i<=m;++i){
        int a;
        cin>>s;
        if(s[0]=='a'){
        a=read();
        if(a>mid) { minheap.push(a);} else { maxheap.push(a);}
        while(minheap.size()>=maxheap.size()) { maxheap.push(minheap.top()); minheap.pop();}
        while(minheap.size()+1<maxheap.size()) {minheap.push(maxheap.top());maxheap.pop();}
        }
        else printf("%d\n",mid=maxheap.top());
    }
    return 0;
}

手动模拟版本

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define fp(i,a,b) for(register int i=a;i<=b;++i)
using namespace std;
int n,t1,t2,size1,size2,mid,m;
int big[400005],small[400005];
char s[10];
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar();
    return x*w;
}
inline void big_put(int x){
    big[++size2]=x;
    int now=size2,next;
    while(now>1){
        next=now>>1;
        if(big[now]<=big[next]) return;
        swap(big[now],big[next]);
        now=next;
    }
}
inline int big_get(){
    int now=1,next,v=big[1];
    big[1]=big[size2--];
    while(now<<1<=size2){
        next=now<<1;
        if(next<size2&&big[next+1]>big[next]) ++next;
        if(big[now]>=big[next]) break;
        swap(big[next],big[now]);
        now=next;
    }
    return v;
}
inline void small_put(int x){
    small[++size1]=x;
    int now=size1,next;
    while(now>1){
        next=now>>1;
        if(small[now]>=small[next]) return;
        swap(small[now],small[next]);
        now=next;
    }
}
inline int small_get(){
    int now=1,next,v=small[1];
    small[1]=small[size1--];
    while(now<<1<=size1){
        next=now<<1;
        if(next<size1&&small[next+1]<small[next]) ++next;
        if(small[now]<=small[next]) break;
        swap(small[next],small[now]);
        now=next;
    }
    return v;
}
int main(){
    n=read();
    for(register int i=1;i<=n;++i){
        t1=read();
        if(t1>mid) small_put(t1);else big_put(t1);
        if(size1>=size2) big_put(small_get());
        if(size1+1<size2) small_put(big_get());
    }
    m=read();
    for(register int i=1;i<=m;++i){
        cin>>s;
        if(s[0]=='a') {
            t1=read();
            if(t1>mid) small_put(t1);else big_put(t1);
            if(size1>=size2) big_put(small_get());
            if(size1+1<size2) small_put(big_get());
        } 
        if(s[0]=='m') printf("%d\n",mid=big[1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值