hdu3282 链表或者对顶堆

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu3282 链表或者对顶堆相关的知识,希望对你有一定的参考价值。

维护序列的动态中位数

第一次用链表做题。。感觉指针指来指去也挺麻烦的。。

本题链表解法就是用数组模拟出一个链表,然后离线输入所有数,排序,按照输入顺序在链表里删除元素,一次性删掉两个,然后中位数指针对应移动即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;
#define maxn 10004

struct smc{
    int val,no;
    bool operator<(smc node)const{
        return val<node.val;
    }
}a[maxn];

int l[maxn],r[maxn],tt,p,n,mid;
int ans[maxn],f[maxn];
 
int main(){
    scanf("%d",&p);
    for(tt=1;tt<=p;tt++){
        scanf("%d%d",&mid,&n);
        printf("%d %d
",tt, n/2+1);
        mid=(1+n)/2;
        for(int i=1;i<=n;i++){scanf("%d",&a[i].val);a[i].no=i;}
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++){l[i]=i-1;r[i]=i+1;f[a[i].no]=i;}
        l[0]=l[1]=100,r[0]=1;
        for(int i=n;i>=1;i-=2){//一次减掉两个数 
            ans[i]=a[mid].val;
            if(f[i]<mid && f[i-1]<=mid) mid=r[mid];
            if(f[i]>mid && f[i-1]>=mid) mid=l[mid]; 
            if(f[i]==mid){
                if(f[i-1]>mid) mid=l[mid];
                else mid=r[mid];
            }    
            //从链表中删去这两个结点
            r[l[f[i]]]=r[f[i]];
            l[r[f[i]]]=l[f[i]];
            r[l[f[i-1]]]=r[f[i-1]];
            l[r[f[i-1]]]=l[f[i-1]];        
        }
        int cnt=0;
        for(int i=1;i<=n;i+=2){
            printf("%d ",ans[i]);
            if(++cnt>=10) puts(""),cnt=0;
        }
        puts("");
    }
    return 0;
}

网上另外一种解法是对顶堆,所谓对顶堆,就是建立一个小根堆q1,大根堆q2,每次读入的数如果比中位数大,那么就把它放入小根堆中,反之放入大根堆中,小根堆元素必须等于大根堆或者是大根堆+1,如果不符合要求就调整,小根堆堆顶元素即是中位数

hdu和poj输出方式有点不一样

#include<bits/stdc++.h>
#define maxn 10005

using namespace std;

priority_queue<int,vector<int>,greater<int> >q1;//小根堆,堆顶中位数 
priority_queue<int,vector<int>,less<int> >q2;//、大根堆 
int T,n,x,cnt,tot,ans[maxn];

void add(int x){
    if(q1.empty()){
        q1.push(x);
        return;
    }
    if(x>q1.top()) q1.push(x);
    else q2.push(x);
    while(q1.size()<q2.size()){
        q1.push(q2.top());
        q2.pop();
    }
    while(q1.size()>q2.size()+1){
        q2.push(q1.top());
        q1.pop();
    }
}

int main(){
    scanf("%d",&T);
    for(int tt=1;tt<=T;tt++){
        scanf("%d%d",&tt,&n);
        printf("%d %d
",tt,n/2+1);
        while(!q1.empty())q1.pop();
        while(!q2.empty())q2.pop();
        cnt=tot=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            add(x);
            if(i%2!=0) ans[tot++]=q1.top(); 
        }
        for(int i=0;i<tot;i++){
            if(i>0 && i%10==0) puts("");
            if(i%10) putchar( );
            printf("%d",ans[i]);
        }
        puts("");
    }
    return 0; 
}

 

以上是关于hdu3282 链表或者对顶堆的主要内容,如果未能解决你的问题,请参考以下文章

黑匣子 对顶堆

浅谈对顶堆

P1168 中位数(对顶堆)

poj 3784(对顶堆)

106. 动态中位数经典 / 对顶堆

Running Median POJ - 3784 (对顶堆/优先队列)