zoukankan      html  css  js  c++  java
  • 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); 
    	 }
    }
    
    每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
  • 相关阅读:
    UVa 10810
    Android UI开发第三十四篇——SlidingPaneLayout
    eclipse安装插件checkstyle
    eas bos 编辑界面 editUIt 属性值为空
    [置顶] 使用U盘安装ubuntu系统
    Ajax核心——XMLHttpRequest基础
    转储指定的数据块并查看TRC信息
    android 获取当前版本号/修改自定义的应用程序的版本号
    poj3101
    [置顶] mysql中的set和enum类型的用法和区别
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/12870875.html
Copyright © 2011-2022 走看看