zoukankan      html  css  js  c++  java
  • [Data]Splay-二叉排序树

    emm接下来讲讲splay,个人比较喜欢splay,其主要操作就是伸展旋转,它的应用比较广泛,对于一个有序序列,它可以实现区间翻转,还可以求区间第k大。

    splay的核心操作-旋转(本人的旋转可能与一般旋转有点不一样):

    通过上图两种旋转我们可以发现一点点规律:若要rotate(x),先获取x为该父亲的右或左节点p,p为1或0,那么x的(p^1)子节点的父亲指向x的父亲,x的父亲的(p)子节点指向

    x的(p^1)子节点,x的父亲只想原有父亲的祖先,同时更新祖先儿子,更新子树大小;我们可以通过循环来使x节点伸展到根;

     1 bool get(int x){
     2     return x==p[p[x].f].son[1];
     3 }
     4 void rorate(int x){
     5     int f=p[x].f,ff=p[p[x].f].f,opt=get(x);
     6     p[f].son[opt]=p[x].son[opt^1];
     7     p[p[x].son[opt^1]].f=f;
     8     if(ff) p[ff].son[get(f)]=x;
     9     else root=x;
    10 
    11     p[x].f=ff;
    12     p[f].f=x;
    13         p[x].son[opt^1]=f;
    14     //    printf("%d %d
    ",f,x);
    15     refresh(f);
    16     refresh(x);
    17 }
    View Code

    其他的话个人觉得应该没什么好讲的了,删除和插入操作都基本和普通平衡树一样。学会splay后可以去刷下luogu的模板题splay,以下为我的代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 #define maxn 100010
      5 struct node{
      6     int size,son[2],f,rev;
      7 }p[maxn];
      8 int root,n,m;
      9 bool get(int x){
     10     return x==p[p[x].f].son[1];
     11 }
     12 void refresh(int x){
     13     if(x){
     14         int size=1;
     15         if(p[x].son[0]) size+=p[p[x].son[0]].size;
     16         if(p[x].son[1]) size+=p[p[x].son[1]].size;
     17         p[x].size=size;
     18     }
     19 }
     20 void build(int l,int r,int f){
     21     if(l>r) return;
     22     int mid=(l+r)/2;
     23     if(f>mid) p[f].son[0]=mid;
     24     else p[f].son[1]=mid;
     25     if(f!=mid) p[mid].f=f;
     26     p[mid].size=1;
     27     if(l==r) return;
     28     build(l,mid-1,mid);
     29     build(mid+1,r,mid);
     30     refresh(mid);
     31 }
     32 void rorate(int x){
     33     int f=p[x].f,ff=p[p[x].f].f,opt=get(x);
     34     p[f].son[opt]=p[x].son[opt^1];
     35     p[p[x].son[opt^1]].f=f;
     36     if(ff) p[ff].son[get(f)]=x;
     37     else root=x;
     38 
     39     p[x].f=ff;
     40     p[f].f=x;
     41         p[x].son[opt^1]=f;
     42     //    printf("%d %d
    ",f,x);
     43     refresh(f);
     44     refresh(x);
     45 }
     46 void rever(int x){
     47     swap(p[x].son[0],p[x].son[1]);
     48     p[p[x].son[0]].rev^=1;
     49     p[p[x].son[1]].rev^=1;
     50     p[x].rev^=1;
     51     //printf("%d %d
    ",p[x].son[0],p[x].son[1]);
     52 }
     53 void splay(int x,bool k){
     54     if(!k){
     55         while(p[x].f){
     56             rorate(x);
     57             root=x;
     58         }
     59         root=x;
     60     }
     61     else{
     62         while(p[p[x].f].f){
     63             rorate(x);
     64         }
     65         p[root].son[1]=x;
     66     }
     67 }
     68 int find(int x){
     69     int now=root;
     70     while(1){
     71         //  printf("%d %d
    ",x,now);
     72         if(p[now].rev) rever(now);
     73         if(p[p[now].son[0]].size>=x){
     74             now=p[now].son[0];
     75         }
     76         else{
     77             if(p[p[now].son[0]].size==x-1) return now;
     78             x-=p[p[now].son[0]].size+1;
     79             now=p[now].son[1];
     80         }
     81     }
     82 }
     83 void dfout(int x){
     84     if(p[x].rev) rever(x);
     85     if(p[x].son[0]) dfout(p[x].son[0]);
     86     if(x>1&&x<n+2) printf("%d ",x-1);
     87     if(p[x].son[1]) dfout(p[x].son[1]);
     88 }
     89 int main()
     90 {
     91     int l,r;
     92     scanf("%d %d",&n,&m);
     93     root=(n+3)/2;
     94     build(1,n+2,root);
     95     while(m--){
     96         scanf("%d %d",&l,&r);
     97         if(l==r) continue;
     98         l=find(l);
     99         r=find(r+2);
    100         splay(l,0);
    101         splay(r,1);
    102         p[p[p[root].son[1]].son[0]].rev^=1;
    103     }
    104     dfout(root);
    105     return 0;
    106 }
    View Code
  • 相关阅读:
    Android 4.0锁屏机制类之间的调用关系
    给盲目兴奋的程序员们的建议
    Hadoop相对于RDBMS、HPC、志愿计算的比较
    vmware7.1.14的vmware tools不支持opensuse12的解决过程
    集群的分类
    Suse linux和OpenSuse的区别和联系
    Apache Hadoop项目
    linux下安装JDK
    sudo的详细用法
    ubuntu和debian环境下vmware虚拟机共享目录无法挂载的问题解决办法
  • 原文地址:https://www.cnblogs.com/Fish-/p/8167726.html
Copyright © 2011-2022 走看看