斐波那契堆模板

题目

测试题目传送门 emmm,其实只写了一部分函数(就这还折腾了整整半天 ),其他的留坑吧= =,而且也没用指针写,常数也很大QAQ

Code

//By zuiyumeng
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Re register
#define Ms(a,b) memset((a),(b),sizeof(a))
#define Fo(i,a,b) for(Re int i=(a),_=(b);i<=_;i++)
#define Ro(i,a,b) for(Re int i=(b),_=(a);i>=_;i--)
using namespace std;

inline int read() { 
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=1e5+10;
int n,m;
int fdeg[N],fa[N];
bool vis[N];
struct Node{
    int key,degree,fa,son,left,right;
    bool deld;//该题特殊要求
}nd[N];
struct Heap{
    int min,n;
}hep[N];

void insrt(int now,int u) {
    Node &x=nd[u]; Heap &h=hep[now];
    x.fa=0;
    if(!h.min) {
        x.left=x.right=u;
        h.min=u;
    } else {
        Node &y=nd[h.min],&z=nd[y.right];
        x.left=z.left; x.right=y.right;
        y.right=z.left=u;
        if(y.key>x.key||(y.key==x.key&&h.min>u)) h.min=u;
        // ||后为该题特殊要求
    }
    h.n++;
}

Heap merge(int u,int v) {
    Heap &h1=hep[u],&h2=hep[v],h;
    Node &a1=nd[h1.min],&b1=nd[a1.right];
    Node &a2=nd[h2.min],&b2=nd[a2.left];
    b1.left=a2.left,b2.right=a1.right;
    a1.right=h2.min,a2.left=h1.min;
    h.min=h1.min;
    if(!h1.min || (h2.min&&a2.key<a1.key)) h.min=h2.min;
    h.n=h1.n+h2.n;
    return h;
}

void link(int now,int u,int v) {
    Node &x=nd[u],&y=nd[v];
    nd[y.left].right=y.right;
    nd[y.right].left=y.left;
    if(x.son) {
        Node &a=nd[x.son],&b=nd[a.right];
        y.left=x.son,y.right=a.right;
        a.right=v,b.left=v;
    } else {
        x.son=v;
        y.left=y.right=v;
    }
    y.fa=u; x.degree++;
}

void consoldate(int now) {
    Ms(fdeg,0);Ms(vis,0);
    Heap &h=hep[now];
    int cur=h.min;
    while(!vis[cur]) {
        int d=nd[cur].degree,nxt=nd[cur].right; vis[cur]=1;
        while(fdeg[d]) {
            Node &y=nd[fdeg[d]],&x=nd[cur];
            if(x.key>y.key||(x.key==y.key&&cur>fdeg[d])) swap(cur,fdeg[d]);
            // ||后为该题特殊要求
            link(now,cur,fdeg[d]);
            fdeg[d]=0; d++;
        }
        fdeg[d]=cur;
        cur=nxt; 
    }
    h.min=0;
    Fo(i,0,ceil(log2((double)h.n))+1) if(fdeg[i]) {
        int u=fdeg[i]; Node &x=nd[u];
        insrt(now,u); h.n--;
    }
}

int deleteMin(int now) {
    Heap &h=hep[now];
    Node &x=nd[h.min];
    if(!h.min) return 0;
    int cur=x.son;
    Fo(i,1,x.degree) {
        int nxt=nd[cur].left;
        insrt(now,cur); h.n--;
        nd[cur].fa=0;
        cur=nxt;
    }
    nd[x.left].right=x.right;
    nd[x.right].left=x.left;
    x.deld=1; x.son=0;
    if(x.right==h.min) h.min=0;
    else { 
        h.min=x.right;
        consoldate(now);
    }
    h.n--;
    return x.key;
}

int getro(int x) {return fa[x]=fa[x]==x?x:getro(fa[x]);}//这个题得用并查集

int main() {
    n=read();m=read();
    Fo(i,1,n) nd[i].key=read(),insrt(i,i),fa[i]=i;
    Fo(i,1,m) { 
        int opt=read();
        if(opt==1) {
            int x=read(),y=read();
            if(nd[x].deld||nd[y].deld) continue;
            int rx=getro(x),ry=getro(y);
            if(rx==ry) continue;
            if(rx>ry) swap(rx,ry);
            hep[rx]=merge(rx,ry);
            fa[ry]=rx;
        } else {
            int x=read();
            if(nd[x].deld) {cout<<"-1"<<endl;continue;}
            int rx=getro(x); 
            cout<<deleteMin(rx)<<endl;
        }
    }
    return 0;
}
上一篇:4.算法调试


下一篇:二叉树