旋转 Treap

宏定义

  • #define TT int:以 TT\text{TT} 为基本类型维护,可根据自己需要定义,这里实现了以 int\text{int} 为基本类型的 Treap\text{Treap}
  • #define pl a[p].lTreap\text{Treap} 中左子树的简写。
  • #define pr a[p].rTreap\text{Treap} 中右子树的简写。
  • #define pv a[p].vala[p].val 的简写。
  • #define pc a[p].cnta[p].cnt 的简写。
  • #define ps a[p].sizea[p].size 的简写。
  • #define pd a[p].data[p].dat 的简写。

常量与变量

  • const TT\text{const TT} INF:一个极值,能保证值为 INFINF 的节点的右子树没有元素,值为 INF-INF 的节点的左子树没有元素。
  • int\text{int} tot:实际存在的节点个数,初始时有两个节点(1,INF)(1,-INF)(2,INF)(2,INF)
  • int\text{int} nc[i]:第 ii 个内存(没有被占用的节点)。
  • int\text{int} rootTreap\text{Treap} 的根节点,一般为 11
  • Tree\text{Tree} a[i]Treap\text{Treap} 的一个节点 ii
  • int\text{int} a[i].l:节点 ii 的左子节点,没有则为 00
  • int\text{int} a[i].r:节点 ii 的右子节点,没有则为 00
  • BST_T\text{BST\_T} a[i].val:节点 ii 的值。
  • int\text{int} a[i].cnt:与节点 ii 的值相同的元素个数,都合并在 aia_i 中。
  • int\text{int} a[i].size:以节点 ii 为根的子树的元素总数(值相同的不算作一个)。
  • int\text{int} a[i].dat:随机的额外权值,以确定 Treap\text{Treap} 的形态。

函数

  • int\text{int} compare(BST_T x,BST_T y):比较 xxyy 的值,可根据需要自己定义。若返回值是一个负整数,如 1-1,则表示 xx 的值应该位于值为 yy 的节点的左子树;若返回值是 00,则表示 xx 的值应该和 yy 属于同一个节点;若返回值是一个正整数,如 11,则表示 xx 的值应该位于值为 yy 的节点的右子树。
  • void\text{void} update(int p):更新 pp 节点的 ap.sizea_p.size
  • int\text{int} get_new(BST_T val):新建一个值为 valval 的节点,返回这个节点的编号。
  • int\text{int} del(int p):删除 pp 节点,放入内存。
  • void\text{void} build():重建树,重整内存。
  • int\text{int} get(int p,BST_T val):找到以 pp 为根的子树中值为 valval 的节点的编号,没有则返回值为 00,调用时 pp 常为 rootroot
  • void\text{void} zig(int &p):右旋 pp 节点。
  • void\text{void} zag(int &p):左旋 pp 节点。
  • void\text{void} insert(int &p,BST_T val):在以 pp 为根的子树中插入一个值为 valval 的元素,计重,调用时 pp 常为 rootroot
  • void\text{void} remove(int &p,BST_T val):在以 pp 为根的子树中删除一个值为 valval 的元素,重复的只删一个,调用时 pp 常为 rootroot
  • int\text{int} get_pre(BST_T val):找到 Treap\text{Treap} 中值为 valval 的元素的前驱的节点编号,即小于 valval 的数中最大的元素值的节点编号,不存在则返回值为 INF-INF 的节点的编号 11
  • int\text{int} get_next(BST_T val):找到 Treap\text{Treap} 中值为 valval 的元素的后继的节点编号,即大于 valval 的数中最小的元素值的节点编号,不存在则返回值为 INFINF 的节点的编号 22
  • int\text{int} V_to_R(int p,BST_T val):在以 pp 为根的子树中寻找值为 valval 的元素的排名,不存在则返回 00,排名就是小于 valval 后继的元素个数,调用时 pp 常为 rootroot
  • BST_T\text{BST\_T} R_to_V(int p,int rank):在以 pp 为根的子树中寻找排名为 rank1rank-1 的元素的值,不存在则返回 MAXMAX,一个元素的排名可能有多个,调用时 pp 常为 rootroot
  • void\text{void} write(int p):输出以 pp 节点为根节点的子树的信息,按先序遍历输出,每个节点的信息包括:该节点编号,该节点值,左子节点编号及值(无则均为 00),右子节点编号及值(无则均为 00)。
#define pl a[p].l
#define pr a[p].r
#define pv a[p].val
#define pc a[p].cnt
#define ps a[p].size
#define pd a[p].dat
struct Treap{
	const TT INF=0x7fffffff;
	int tot,root,nc[N];
	struct Tree{
		int l,r;
		TT val;
		int dat,cnt,size;
	}a[N];
	int compare(TT x,TT y){
        if(x<y)
            return -1;
        if(x==y)
            return 0;
        if(x>y)
            return 1;
    }
    void update(int p){
        ps=a[pl].size+a[pr].size+pc;
    }
    int get_new(TT val){
    	int p=nc[++tot];
        pv=val;
        pc=ps=1;
        pl=pr=0;
        pd=rand();
        return p;
    }
    void del(int &p){
    	nc[tot--]=p;
    	p=0;
	}
    void build(){
        tot=0;
        for(int i=1;i<N;i++)
        	nc[i]=i;
        get_new(-INF);get_new(INF);
        a[root=1].r=2;
        update(root);
    }
    int get(int p,TT val){
        if(!p)
            return 0;
        if(!compare(val,pv))
            return p;
        return get((compare(val,pv)<0?pl:pr),val);
    }
    void zig(int &p){
		int q=pl;
		pl=a[q].r;a[q].r=p;p=q;
		update(pr);update(p);
	}
    void zag(int &p){
		int q=a[p].r;
		pr=a[q].l;a[q].l=p;p=q;
		update(pl);update(p);
	}
    void insert(int &p,TT val){
        if(!p){
            p=get_new(val);
            return;
        }
        if(!compare(val,pv)){
            pc++;
            update(p);
            return;
        }
        if((compare(val,pv)<0)){
            insert(pl,val);
            if(pd<a[pl].dat)
            	zig(p);
		}
        else{
            insert(pr,val);
            if(pd<a[pr].dat)
            	zag(p);
		}
        update(p);
    }
    void remove(int &p,TT val){
        if(p==0)
            return;
        if(!compare(val,pv)){
            if(pc>1){
                pc--;
                update(p);
                return;
            }
            if(pl||pr){
				if(!pr||a[pl].dat>a[pr].dat){
					zig(p);
					remove(pr,val);
				}
				else{
					zag(p);
					remove(pl,val);
				}
				update(p);
				return;
			}
			del(p);
			return;
        }
        if((compare(val,pv)<0)) 
            remove(pl,val);
        else
            remove(pr,val);
        update(p);
    }
    int get(int p,int val){
		if(!p)
			return 0;
		if(val==pv)
			return p;
		return get((val<pv?pl:pr),val);
	}
    int get_pre(TT val){
        int ans=1,p=root;
        while(p){
            if(!compare(val,pv)){
                if(pl){
                    p=pl;
                    while(pr)
                        p=pr;
                    ans=p; 
                }
                break;
            }
            if((compare(pv,val)<0&&compare(pv,a[ans].val)>0))
                ans=p;
            p=(compare(val,pv)<0?pl:pr);
        }
        return ans;
    }
    int get_next(TT val){
        int ans=2,p=root;
        while(p){
            if(!compare(val,pv)){
                if(pr){
                    p=pr;
                    while(pl)
                        p=pl;
                    ans=p;
                }
                break;
            }
            if((compare(pv,val)>0&&compare(pv,a[ans].val)<0))
                ans=p;
            p=(compare(val,pv)<0?pl:pr);
        }
        return ans;
    }
    int V_to_R(int p,TT val){//val to rank
        if(!p)
            return 0;
        if(!compare(val,pv))
            return a[pl].size;
        if(compare(val,pv)<0)
            return V_to_R(pl,val);
        return V_to_R(pr,val)+a[pl].size+pc;
    }
    TT R_to_V(int p,int rank){//rank to val
        if(!p)
            return INF;
        if(a[pl].size>=rank)
            return R_to_V(pl,rank);
        if(a[pl].size+pc>=rank)
            return pv;
        return R_to_V(pr,rank-a[pl].size-pc);
    }
    void write(int p){
    	if(!p)
    		return;
    	printf("%d  val:%d  lson:%d %d  rson:%d %d\n",p,pv,pl,a[pl].val,pr,a[pr].val);
    	write(pl);write(pr);
	}
}tree;
posted @ 2021-12-10 13:21  luckydrawbox  阅读(9)  评论(0)    收藏  举报  来源