斜堆

斜堆是一种可并堆。
我们需要维护可并堆森林,因此用并查集维护每个节点所属可并堆的根。
为了防止权值相同的情况,我们以编号作为偏序关系的第二关键字。

merge

merge实现合并两棵斜堆。
假如我们要合并的两个斜堆根是\(u,v\),不妨设\(val_u<val_v\)
然后递归合并\(u\)的右儿子和\(v\),将递归合并后的根\(u\)的右儿子。
合并完之后需要交换\(u\)的左右儿子以保证复杂度,记得维护并查集。
然后交换最后维护一下并查集。


int merge(int x,int y)
{
    if(!x||!y) return x|y;
    if(val[x]>val[y]||(val[x]==val[y]&&x>y)) std::swap(x,y);
    return rc=merge(rc,y),std::swap(lc,rc),fa[lc]=fa[rc]=fa[x]=x,x;
}

pop

pop实现弹出某个节点所在斜堆的根\(x\)
直接把根的左右儿子合并起来就好了。
注意还要维护并查集,因为原斜堆中部分点在并查集中的的父亲为\(x\),所以要将\(x\)在并查集中的父亲设置为新的斜堆的根。

void pop(int x){val[x]=-1,fa[lc]=lc,fa[rc]=rc,fa[x]=merge(lc,rc);}
posted @ 2020-01-07 22:39  Shiina_Mashiro  阅读(257)  评论(0编辑  收藏  举报