splay单双旋还挺有意思的,一直觉得单旋是ok的,但是感性画图分析了一波~
单旋:直接旋转我自己
双旋:先旋转我的父亲,再旋转我自己
对于链结构,我们需要双旋,画图之后发现,我们采用双旋会至少压一层,而单旋则一直维持链式结构,显然单旋会被卡成O(n)
其余的结构而言,单旋双旋并无多大区别,但需要注意的是,双旋也存在一种结构被卡,但卡成连后就会被压层,而单旋则可能一直被卡,因此均摊复杂度还是log2(n)
详细的复杂度证明Tarjan用到了势能这个概念orz,具体有兴趣的同学可以上网查一查
struct Splay{
#define N 100010
int k[N]siz[N];
int rt,cnt,p[N],ch[N][2];
#define Ls(v) ch[v][0]
#define rs(v) ch[v][1]
inline void maintain(int x){
siz[x]=siz[Ls(x)]+siz[rs(x)]+1;
}
inline void rot(int x){
int f=p[x],gf=p[f],type=rs(f)==x,son=ch[x][!type];
ch[p[son]=f][type]=son,maintain(f);
ch[p[f]=x][!type]=f,maintain(x);
ch[p[x]=gf][rs(gf)==f]=x;
}
inline void splay(int x,int goal){//旋转在目标的下面
if(x==goal)return ;
while(p[x]^goal){
if((p[p[x]]^goal)&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rot(p[x]);
rot(x);
}
if(!goal)rt=x;
}
};
可读性还是蛮高的……其实我不是压行选手~