可以将两个堆合并的堆
1.斜堆
最主要的操作----
int merge(int x,int y)
{
if(!x) return y;//x为空,返回y
if(!y) return x;//同理
//为了方便,将y接在x的子树上
if(a[x].val<a[y].val)//小根堆
swap(x,y);
a[x].r=merge(a[x].r,y);
swap(a[x].r,a[x].l);//不然显得很不平衡
//感性理解下就好
return x;
}
val 为值,返回的为根的编号,a[x].l , r 均为编号
2.随机堆
加了一个玄乎操作,跑得最快
int merge(int x,int y)
{
if(!x) return y;//x为空,返回y
if(!y) return x;//同理
//为了方便,将y接在x的子树上
if(a[x].val<a[y].val)//小根堆
swap(x,y);
a[x].r=merge(a[x].r,y);
if(rand()%2) swap(a[x].r,a[x].l);//随机
//感性理解下就好
return x;
}
3.左偏树
没有什么用的东西
上面是随机堆跑的,左偏树明显慢地多
定义dis[i]为到叶子节点的距离
则左儿子的dis永远比右儿子
不过还是学一下吧
int merge(int x,int y)
{
if(!x) return y;
if(!y) return x;
if(a[x].val<a[y].val) swap(x,y);
a[x].r=merge(a[x].r,y);
if(dis[a[x].r]>dis[a[x].l]||!a[x].l) swap(a[x].r,a[x].l);//左儿子要比右儿子大
dis[x]=dis[a[x].r]+1;
return x;
}
如果用STL呢
//配对堆
#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef __gnu_pbds::priority_queue <int,less<int>,pairing_heap_tag> heap;
typedef heap::point_iterator it;
除了pop()全是O(1)
还有很多黑科技,大家可以上网查
没时间是还是可以用的,但最好自己写