【模板】左偏树

左偏树是可合并堆的一种实现方式,可合并堆还有其他实现方式比如斜堆,然而我这种蒟蒻只会写左偏树。

模板里的左偏树为大根堆,支持合并,查询堆顶和弹出堆顶操作,对于已经删除的位置,查询将返回-1,为了确保弹出的正常进行,模板里使用的并查集没有使用路径压缩,因此常数可能会比较大。

 1 #include<stdio.h>
 2 #define maxn 1000
 3 struct node{int ch[2],w,dist;};
 4 int n,op,ori[maxn];
 5 void swp(int &x,int &y){x^=y;y^=x;x^=y;}
 6 struct ltt
 7 {
 8     node lt[maxn];
 9     int fa[maxn]; bool sta[maxn];
10     //int fi(int p){if(fa[p]!=p){fa[p]=fi(fa[p]);}return fa[p];}
11     int fi(int p){return fa[p]==p?p:fi(fa[p]);}
12     void ini()
13     {for(int i=1;i<=n;i++) fa[i] = i,lt[i].w = ori[i];}
14     int merge(int p,int q)
15     {
16         if(!p||!q) return !p ? q : p;
17         if(lt[p].w<lt[q].w) swp(p,q);
18         lt[p].ch[1] = merge(q,lt[p].ch[1]);
19         if(!lt[p].ch[0]||lt[lt[p].ch[0]].dist<lt[lt[p].ch[1]].dist) swp(lt[p].ch[0],lt[p].ch[1]);
20         lt[p].dist = !lt[p].ch[1] ? 0 : lt[lt[p].ch[1]].dist + 1;
21         return p;
22     }
23     void mer(int p,int q)//合并p位置和q位置所在的左偏树
24     {
25         if(sta[p]||sta[q]||fi(p)==fi(q)) return;
26         fa[fi(p)]=fa[fi(q)]=merge(fi(p),fi(q));
27     }
28     int top(int p)//返回p位置所在堆的堆顶,如果p位置已经被删除,返回-1
29     {
30         int r = fi(p); if(sta[r]) return -1;
31         return lt[r].w;
32     }
33     int exmax(int p)//弹出p位置所在堆的堆顶,如果p位置已被删除,返回-1
34     {
35         int r = fi(p); if(sta[r]) return -1;
36         sta[r] = true;
37         int lc = lt[r].ch[0],rc = lt[r].ch[1];
38         fa[lc] = fa[rc] = merge(lc,rc);
39         return lt[r].w;
40     }
41 }T;
42 int main()
43 {
44     scanf("%d%d",&n,&op);
45     int i,p,q,flag;
46     for(i=1;i<=n;i++) scanf("%d",ori+i);
47     T.ini();
48     for(i=1;i<=op;i++)
49     {
50         scanf("%d",&flag);
51         if(flag==1)
52         {scanf("%d%d",&p,&q);T.mer(p,q);}
53         else if(flag==2){scanf("%d",&p);printf("%d
",T.exmax(p));}
54         else{scanf("%d",&p);printf("%d
",T.top(p));}
55     }
56     return 0;
57 }
View Code
原文地址:https://www.cnblogs.com/hzs2000/p/6711113.html