SPLAY 模板

经典引文

空间效率:O(n)
时间效率:O(log n)插入、查找、删除
创造者:Daniel Sleator 和 Robert Tarjan
优点:每次查询会调整树的结构,使被查询频率高的条目更靠近树根。

Tree Rotation


 
树的旋转是splay的基础,对于二叉查找树来说,树的旋转不破坏查找树的结构。
 

Splaying

 
Splaying是Splay Tree中的基本操作,为了让被查询的条目更接近树根,Splay Tree使用了树的旋转操作,同时保证二叉排序树的性质不变。
Splaying的操作受以下三种因素影响:
  • 节点x是父节点p的左孩子还是右孩子
  • 节点p是不是根节点,如果不是
  • 节点p是父节点g的左孩子还是右孩子
同时有三种基本操作:

Zig Step


当p为根节点时,进行zip step操作。
当x是p的左孩子时,对x右旋;
当x是p的右孩子时,对x左旋。
 

Zig-Zig Step

当p不是根节点,且x和p同为左孩子或右孩子时进行Zig-Zig操作。
当x和p同为左孩子时,依次将p和x右旋;
当x和p同为右孩子时,依次将p和x左旋。
 
 

Zig-Zag Step

当p不是根节点,且x和p不同为左孩子或右孩子时,进行Zig-Zag操作。
当p为左孩子,x为右孩子时,将x左旋后再右旋。
当p为右孩子,x为左孩子时,将x右旋后再左旋。
总结:
    rotate操作的核心是把点和其父亲换位置,然后维护中序就好了。
   我们可以通过复杂度分析发现是log级的。
文艺平衡树:
#pragma GCC optimize("-O2")
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int f[N],ch[N][2],siz[N],rev[N],rt;
#define Mid (l+r>>1)
#define sight(x) ('0'<=x&&x<='9')
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
inline void pb(int x){
    siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];
}
inline void pd(int x){
    if (!rev[x]) return ;
    swap(ch[x][0],ch[x][1]);
    rev[ch[x][0]]^=1,rev[ch[x][1]]^=1; rev[x]=0;
}
int build(int l,int r,int fa){
    if (l>r) return 0; f[Mid]=fa;
    ch[Mid][0]=build(l,Mid-1,Mid);
    ch[Mid][1]=build(Mid+1,r,Mid);
    pb(Mid); return Mid;
}
int x,y,z,kind;
void rotate(int x,int &k) {
    int y=f[x],z=f[y],kind=(ch[y][0]==x);
    if (y==k) k=x;else {ch[z][ch[z][0]!=y]=x;}
       ch[y][kind^1]=ch[x][kind]; f[ch[y][kind^1]]=y;
       ch[x][kind]=y; f[y]=x; f[x]=z;
       pb(x); pb(y);
}
void splay(int x,int &k){
    while (x^k) {
        int y=f[x],z=f[y];
        if (y^k) {
            if ((ch[y][0]==x)^(ch[z][0]==y)) rotate(x,k); 
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
int s,n,m,l,r;
int find(int x,int k) {
    pd(x); s=siz[ch[x][0]];
    if (k==s+1) return x;
    if (k<=s) return find(ch[x][0],k);
    else return find(ch[x][1],k-s-1);
}
void rever(int l,int r){
    x=find(rt,l); y=find(rt,r+2);
    splay(x,rt); splay(y,ch[x][1]); 
    rev[ch[y][0]]^=1;
}
signed main () {
    freopen("testdata.in","r",stdin);
    read(n); read(m); rt=n+3>>1;
    ch[rt][0]=build(1,rt-1,rt);
    ch[rt][1]=build(rt+1,n+2,rt);
    while (m--) {
        read(l); read(r);
        rever(l,r);
    }
    for (int i=2;i<=n+1;i++) writel(find(rt,i)-1);
}

 

 
 
posted @ 2018-03-15 20:34  泪寒之雪  阅读(179)  评论(0编辑  收藏  举报