zoukankan      html  css  js  c++  java
  • [模板] 左偏树

    左偏树

    用途

    支持(O(log n))合并,(O(log n))删除堆顶,(O(log n))查找,(O(1))取最小值的堆.

    定义

    对于左偏树中的一个节点x,离它最近的一个叶子结点经过的边数称为它的距离,记为 (dist(x)) .特别地,外结点的距离为0,空节点(null)的距离为-1.

    对于左偏树中的任意节点,满足它的左子树的距离大于等于右子树的距离.

    代码

    int val[nsz];
    struct tnd{int v,l,r,d,f;}tree[nsz];
    void init(){rep(i,1,n)tree[i].v=val[i];}
    int merge(int a,int b){//b -> a
    	if(a==0||b==0)return a+b;
    	if(tree[a].v>tree[b].v||(tree[a].v==tree[b].v&&a>b))swap(a,b);
    	tree[a].r=merge(tree[a].r,b);
    	tree[tree[a].r].f=a;
    	if(tree[tree[a].l].d<tree[tree[a].r].d)swap(tree[a].l,tree[a].r);
    	tree[a].d=tree[tree[a].r].d+1;
    	return a;
    }
    int getf(int x){
    	while(tree[x].f)x=tree[x].f;
    	return x;
    }
    void del(int x){
    	val[x]=-1;
    	tree[tree[x].l].f=tree[tree[x].r].f=0;
    	merge(tree[x].l,tree[x].r);
    }
    
    //merge two heaps
    	if(val[a]==-1||val[b]==-1||a==b)continue;
    	a=getf(a),b=getf(b);
    	if(a==b)continue;
    	merge(getf(a),getf(b));
    
    //delete top
    	if(val[a]==-1)continue;
    	else a=getf(a),cout<<val[a]<<'
    ',del(a);
    
    

    板子,bzoj1455-罗马游戏

    随机偏堆

    每次合并的时候, 不需要判断两边的深度或者大小, 直接 rand() 得到要合并的儿子.

    容易发现期望意义下复杂度是正确的, 与左偏树相同.

    炒鸡好写...

    int merge(int u,int v){
        int p=val[u]>val[v]?u:v,x=rand()&1;
        return (u&&v)?(ch[p][x]=merge(ch[p][x],u+v-p),p):(u|v);
    }
    
  • 相关阅读:
    某些电脑前面板没声音问题
    安装win10笔记
    linux 时区问题
    JS实现网页飘窗
    缓存promise技术不错哦
    wepy相关
    生成keystore
    2017年终巨献阿里、腾讯最新Java程序员面试题,准备好进BAT了吗
    细思极恐-你真的会写java吗
    年终盘点:Java今年的大事记都在这里!
  • 原文地址:https://www.cnblogs.com/ubospica/p/9871271.html
Copyright © 2011-2022 走看看