Splay平衡树

__以前认为平衡树一点也不好理解,可是学了之后发现还可以,就是代码有点多,但是功能真的是很强大, __学习来源
普通平衡树为例
这个splay最重要的是一个splay, 直接将某个点转到根节点, 如果想进行一些操作, 可以直接在上面操作了,


#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10 ;
int f[N] , cnt[N] , ch[N][2] , size[N] , key[N] , sz , rt ;
void clear(int x)
{
	f[x] = cnt[x] = ch[x][0] = ch[x][1] = size[x]  = key[x] = 0 ;
} 
bool get(int x)
{
	return ch[f[x]][1] == x ;
}
void pushup(int x)
{
    if (x)
    {
        size[x]=cnt[x];
        if (ch[x][0]) size[x]+=size[ch[x][0]];
        if (ch[x][1]) size[x]+=size[ch[x][1]];
    }
}
void rotate(int x)
{
	int old = f[x] , oldf = f[old] , which = get(x) ;
	ch[old][which] = ch[x][which ^ 1] ;
	f[ch[old][which]] = old ;
	ch[x][which ^ 1] = old , f[old] = x ;
	f[x] = oldf ;
	if(oldf)
	 ch[oldf][ch[oldf][1] == old] = x ;
	pushup(old) , pushup(x) ;
}
void splay(int x)
{
	for(int fa ; fa = f[x] ; rotate(x))
	 if(f[fa])
	  rotate(get(x) == get(fa) ? fa : x ) ;
	rt = x ; 
}
void insert(int x)
{
	if(rt == 0)
	 {
	 	sz ++ , key[sz] = x , rt = sz ;
	 	cnt[sz] = size[sz] = 1 ;
	 	f[sz] = ch[sz][1] = ch[sz][0] = 0 ;
	 	return ;
	 }
	 int now = rt , fa = 0 ;
	 while(1)
	 {
	 	if(x == key[now])
	 	 {
	 	 	cnt[now] ++ , pushup(now) , pushup(fa) , splay(now) ;
	 	 	return ;
		  }
		fa = now , now = ch[now][key[now] < x] ;
		if(now == 0)
		 {
		 	sz ++ ;
		 	size[sz] = cnt[sz] = 1 ;
		 	ch[sz][0] = ch[sz][1] = 0 ;
		 	ch[fa][x > key[fa]] = sz ;
		 	f[sz] = fa ;
		 	key[sz] = x ;
		 	pushup(fa) ;
		 	splay(sz) ;
		 	return ;
		 }
	 }
}
int rnk(int x)
{
	int now = rt , ans = 0 ;
	while(1)
	 {
	 	if(x < key[now]) now = ch[now][0] ;
	 	else 
	 	 {
	 	 	ans += size[ch[now][0]] ;
	 	 	if(x == key[now])
	 	 	 {
	 	 	    splay(now) ;
				return ans + 1 ;	
			 }
			 ans += cnt[now] ;
			 now = ch[now][1] ;
		 }
	 }
}
int kth(int x)
{
	int now = rt ;
	while(1)
	 {
	 	if(ch[now][0] && x <= size[ch[now][0]]) 
	 	 now = ch[now][0] ;
	 	else 
	 	 {
	 	 	int temp = size[ch[now][0]] + cnt[now] ;
	 	 	if(x <= temp)
	 	 	 return key[now] ;
	 	 	x -= temp , now = ch[now][1] ;
		  }
	 }
}
int pre()
{
	int now = ch[rt][0] ;
	while(ch[now][1]) now = ch[now][1] ;
	return now ;
}
int next()
{
	int now = ch[rt][1] ;
	while(ch[now][0])
	 now = ch[now][0] ;
	return now ;
}
void del(int x)
{
	rnk(x) ;
	if(cnt[rt] > 1) 
	 {
	 	cnt[rt] -- , pushup(rt) ;
	 	return ;
	 }
	 if(!ch[rt][1] && !ch[rt][0])
	  {
	  	clear(rt) , rt = 0 ;
	  	return ;
	  }
	  if(!ch[rt][0])
	   {
	   	int oldrt = rt; 
		   rt = ch[rt][1] , f[rt] = 0 , clear(oldrt) ;
	   	return ;
	   }
	 else if(!ch[rt][1])
	  {
	  	int oldrt = rt ; rt = ch[rt][0] ;
	  	f[rt] = 0 , clear(oldrt) ;
	  	return ;
	  }
	  int oldrt = rt ;
	  int leftbig = pre() ;
	  splay(leftbig) ;
	  ch[rt][1] = ch[oldrt][1] ;
	  f[ch[oldrt][1]] = rt ;
	  clear(oldrt) ;
	  pushup(rt) ; 
}
int main()
{
	int n ;
	scanf("%d" , &n) ;
	for(int i = 1; i <= n ;i ++)
	 {
	 	int type , k ;
	 	scanf("%d%d" , &type , &k) ;
	 	if(type == 1) insert(k) ;
	 	else if(type == 2) del(k) ;
	 	else if(type == 3) cout << rnk(k) << endl ;
	 	else if(type == 4) cout << kth(k) << endl ;
	 	else if(type == 5) insert(k) , cout << key[pre()] << endl , del(k) ;
	 	else if(type == 6) insert(k) , cout << key[next()] << endl , del(k); 
	 }
}
posted @ 2019-10-29 17:15  spnooyseed  阅读(115)  评论(0编辑  收藏  举报