[知识点]Splay tree指针实现

Posted hallmeow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[知识点]Splay tree指针实现相关的知识,希望对你有一定的参考价值。

早就想在成都把$splay$改成指针打法了。当时竟然没调出来。指针真难调。早上重新打了一遍,改过来了。

其实是为了打$lct$的。指针感觉会快,喵喵喵?

普通平衡树模板:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define N 101000
#define lc(x) (x->ch[0])
#define rc(x) (x->ch[1])
#define fa(x) (x->fa)
#define size(x) (x->size)
struct Splay{
	Splay *ch[2],*fa;
	int size,w,v;
	Splay(int x=0){ch[0]=ch[1]=fa=NULL;size=w=1;v=x;}
}*null,*root;
void init(){
	null=new Splay(0);
	lc(null)=rc(null)=fa(null)=null;null->size=null->w=0;
	root=null;
}
bool get(Splay *rt){return rc(rt->fa)==rt;}
void update(Splay *rt){if(rt) rt->size=size(lc(rt))+size(rc(rt))+rt->w;}
Splay *xin(Splay *fa,int x){
	Splay *now=new Splay(x);
	lc(now)=rc(now)=null;fa(now)=fa;
	if(fa!=null){
		fa->ch[fa->v < x]=now;
		update(fa);
	} 
	return now;
}
void rotate(Splay *&rt){
	Splay *old=fa(rt),*oldf=fa(old);
	int d=get(rt);
	Splay *t=rt;old->ch[d]=t->ch[d^1];old->ch[d]->fa=old;
	t->ch[d^1]=old;old->fa=t;t->fa=oldf;
	if(oldf!=null) oldf->ch[rc(oldf)==old]=t;
	update(old);update(t);
	rt=t;
}
void splay(Splay *rt){
	for(Splay *fa;(fa=fa(rt))!=null;rotate(rt)){
		if(fa(fa)!=null) rotate((get(rt)==get(fa))?fa:rt);
	}
	root=rt;
}
void insert(Splay *&rt,Splay *fa,int x){
	if(rt==null){
		rt=xin(fa,x);splay(rt);
		return;
	}
	if(rt->v==x){
		rt->w++;update(rt);splay(rt);return;
	}
	int d=rt->v < x;
	insert(rt->ch[d],rt,x);
}
int pai(Splay *rt,int x){
	if(rt==null) return 0;
	if(x>rt->v) return size(lc(rt))+rt->w+pai(rc(rt),x);
	else if(x==rt->v){
		int ans=size(lc(rt))+1;splay(rt);
		return ans;;
	} 
	else return pai(lc(rt),x);
}
int kth(Splay *rt,int k){
	if(k<=size(lc(rt))) return kth(lc(rt),k);
	else{
		int temp=size(lc(rt))+rt->w;
		if(k<=temp) return rt->v;
		else return kth(rc(rt),k-temp);
	}
}
Splay *pre(){
	Splay *now=lc(root);
	while(rc(now)!=null) now=rc(now);
	return now;
}
Splay *next(){
	Splay *now=rc(root);
	while(lc(now)!=null) now=lc(now);
	return now;
}
void del(int x){
	int whatever=pai(root,x);
	if(root->w>1){root->w--;update(root);return;}
	if(lc(root)==null&&rc(root)==null){root=null;return;}
	if(lc(root)==null){Splay *t=rc(root);delete root;root=t;root->fa=null;return;}
	if(rc(root)==null){Splay *t=lc(root);delete root;root=t;root->fa=null;return;}
	Splay *leftbig=pre(),*oldroot=root,*t=rc(oldroot);
	splay(leftbig);rc(root)=t;delete oldroot;fa(t)=root;
	update(root); 
}
void dfs(Splay *rt){
	if(rt==null) return;
	cout<<rt->v<<endl;
	dfs(lc(rt));dfs(rc(rt));
}
int main(){
	init();
	int n,opt,x; 
    scanf("%d",&n); 
    for (int i=1;i<=n;++i){ 
        scanf("%d%d",&opt,&x); 
        switch(opt){ 
            case 1: insert(root,null,x); break; 
            case 2: del(x); break; 
            case 3: printf("%d\n",pai(root,x)); break; 
            case 4: printf("%d\n",kth(root,x)); break; 
            case 5: insert(root,null,x); printf("%d\n",pre()->v); del(x); break; 
            case 6: insert(root,null,x); printf("%d\n",next()->v); del(x); break; 
        } 
    } 
	return 0;
}

  

以上是关于[知识点]Splay tree指针实现的主要内容,如果未能解决你的问题,请参考以下文章

BBST 之伸展树 (Splay Tree)

BST, AVL Tree 和 Splay Tree 的实现

LCT(link cut tree) 动态树

splay总结

splay tree旋转操作 hdu 1890

Splay Tree(伸展树)