左偏树(可并堆)学习笔记
引入:堆是一种很常用的数据结构,可以在
下面来引入一种新的数据结构——左偏树。顾名思义,这是一颗树,但是向左偏。首先定义一个
而左偏的性质,若设左儿子右儿子分别为
利用这一性质,我们可以进行合并操作。合并时,只需要维护堆性质和左偏树性质即可。
int fa[N], ls[N], rs[N], val[N], dis[N]; int find(int x){ if(fa[x] ^ x){ fa[x] = find(fa[x]); } return fa[x]; } int merge(int x, int y){ if(!x || !y){ return x+y; } if(val[x] > val[y]){ swap(x, y); } rs[x] = merge(rs[x], y), fa[rs[x]] = x; if(dis[ls[x]]<dis[rs[x]]) swap(ls[x], rs[x]); dis[x] = dis[rs[x]]+1; return x; }
因为每次往下走一层,
如何删除堆顶元素呢?只需要合并左右儿子。
void del(int x){ val[x] = -1 ,fa[ls[x]] = ls[x], fa[rs[x]] = rs[x]; fa[x] = merge(ls[x], rs[x]); }