模板左偏树
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板左偏树相关的知识,希望对你有一定的参考价值。
左偏树是可合并堆的一种实现方式,可合并堆还有其他实现方式比如斜堆,然而我这种蒟蒻只会写左偏树。
模板里的左偏树为大根堆,支持合并,查询堆顶和弹出堆顶操作,对于已经删除的位置,查询将返回-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\n",T.exmax(p));} 54 else{scanf("%d",&p);printf("%d\n",T.top(p));} 55 } 56 return 0; 57 }
以上是关于模板左偏树的主要内容,如果未能解决你的问题,请参考以下文章