splay和不加任何旋转一定会被卡的二叉搜索树的唯一区别就是每次操作把当前节点旋转到根。

旋转有各种zig、zag的组合方式,感觉很麻烦,并不对劲的人并不想讲。

其实可以找出一些共性将它们合并。设ls(a)=[点a是其父亲的左儿子],son[a][0]=a的左儿子,son[a][1]=a的右儿子,fa[a]=a的父亲。会发现单旋u时,有变动的点只有son[u][ls(u)^1],u,fa[u],fa[fa[u]]。再仔细想想,儿子有变动的有fa[fa[u]](son[fa[fa[u]]][ls(fa[u])]=u)、fa[u](son[fa[u]][ls(u)]=son[u][ls(u)^1])、u(son[u][ls(u)^1]=fa[u]),父亲有变化的是fa[u](fa[fa[u]]=u)、u(fa[u]=fa[fa[u]])、son[u][ls(u)^1](fa[son[u][ls(u)^1]=fa[u])。都有三组,好记(可能吧…)又好写。

而当双旋u时,若u,fa[u],fa[fa[u]]不共线(即ls(u)^ls(fa[u])==1),则先单旋u,再单旋u;反之,则先单旋fa[u],再单旋u。每次旋转如果深度不小于2就双旋,否则单旋。这样写起来就会很容易了。

根据刚刚的旋转方法,可以看出每次被旋转到根的节点至多经历一次单旋。

至于时间复杂度,在刚学splay时就觉得它很不靠谱,因为感觉每次把某个节点旋转到根并不能缩短多少时间。后来发现每次操作总会进行很多次双旋,双旋总能让这个树变的和你想象中不太一样。

至于严格证明什么的,还是交给手健康的人手推吧,这里并不是对劲的splay。

例题:洛谷2286 [HNOI2004]宠物收养场

并不觉得这题有什么好说的。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<cstdlib>
#define maxn 80001
#define inf 1ll<<32
#define mod 1000000
#define ll long long
using namespace std;
ll read(){
ll x=,f=;
char ch=getchar();
while(isdigit(ch)== && ch!='-')ch=getchar();
if(ch=='-')f=-;
while(isdigit(ch))x=x*+ch-'',ch=getchar();
return x*f;
}
ll n,f;
ll ans;
typedef struct node
{
ll son[],fa;//0左,1右
ll key;
}Tree;
struct Splay
{
ll cnt,root;
Tree x[maxn];
inline void rot(ll u){
ll fu=x[u].fa,ffu=x[fu].fa,l=(x[fu].son[]==u),r=l^;
ll l2=(fu==x[ffu].son[]);
x[ffu].son[l2]=u;
x[u].fa=ffu;
x[fu].fa=u;
x[fu].son[l]=x[u].son[r];
x[x[u].son[r]].fa=fu;
x[u].son[r]=fu;
}
inline void splay(ll u,ll k){
while(x[u].fa!=k){
ll fu=x[u].fa,ffu=x[fu].fa;
if(ffu!=k){
if((x[ffu].son[]==x[u].fa)^(x[fu].son[]==u))
rot(u);
else rot(fu);
}
rot(u);
}
if(k==)root=u;
}
inline void ins(ll k){
ll lk=nxt_no_equ(k,),
rk=nxt_no_equ(k,);
splay(lk,),splay(rk,lk);
x[rk].son[]=++cnt;
x[cnt].fa=rk,x[cnt].son[]=x[cnt].son[]=,x[cnt].key=k;
splay(cnt,);
}
inline void fnd(ll k){
ll u=root;
if(u==)return;
while(x[u].son[k>x[u].key] && k!=x[u].key)
u=x[u].son[k>x[u].key];
splay(u,);
}
inline ll nxt_no_equ(ll k,ll f){//f==1 bigger
fnd(k);
ll u=root;
if(x[u].key>k && f)return u;
if(x[u].key<k && f==)return u;
u=x[u].son[f];
while(x[u].son[f^])u=x[u].son[f^];
return u;
}
inline ll nxt_yes_equ(ll k,ll f){
fnd(k);
ll u=root;
if(x[u].key>=k && f)return u;
if(x[u].key<=k && f==)return u;
u=x[u].son[f];
while(x[u].son[f^])u=x[u].son[f^];
return u;
}
inline void del(ll k){
ll lk=nxt_no_equ(k,),
rk=nxt_no_equ(k,);
splay(lk,),splay(rk,lk);
x[rk].son[]=;
}
void start(){
cnt=;
root=;
ins(inf);ins(-inf);
}
}t;
int main()
{
n=read();
t.start();
for(ll i=;i<=n;i++)
{// x,f=0 pet , x,f=1 people
ll x=read(),y=read();
if(f==){
t.ins(y);
}
else{
if(x==(f<))t.ins(y);
else{
ll lt=t.x[t.nxt_no_equ(y,)].key,
rt=t.x[t.nxt_no_equ(y,)].key,
ttt=abs(lt-y)<=abs(rt-y)?lt:rt;
ans+=abs(ttt-y);
t.del(ttt);
}
}
f+=(x==)?-:;
ans%=mod;
}
cout<<ans%mod;
return ;
}

并不对劲的splay

最新文章

  1. DTO – 服务实现中的核心数据
  2. Entity Framework 6 Recipes 2nd Edition(13-1)译 -&gt; 优化TPT继承模型的查询
  3. Android -- 自定义带进度条的按钮
  4. Empire C:Basic 4
  5. stm32定义GPIO口方向和操作的代码
  6. ES6-Symbol
  7. Difference Between Primes
  8. MinGW 介绍
  9. 记录一次无厘头的粗心失误——java后台报错:Unknown column &#39;xxx&#39; in &#39;field list&#39;
  10. nginx配置vue项目部署访问无问题,刷新出现404问题
  11. JS实现排序算法
  12. 【Java】 剑指offer(14) 二进制中1的个数
  13. [No000011B]为什么有些程序员悄无声息渡过35岁中年危机?
  14. 58A
  15. 生成word附件和word域动态赋值
  16. 12 MySQL--内置功能介绍
  17. UWA发布 | 2017 Unity手游体检蓝皮书 — ARPG篇
  18. java:transient是什么,有什么作用
  19. 学习笔记(1)centos7 下安装nginx
  20. lintcode433 岛屿的个数

热门文章

  1. POJ1690 简单运算去括号
  2. hdu 4539
  3. 没有上司的舞会(hdu 1520)
  4. 【2018 Multi-University Training Contest 4】
  5. 利用PHP SOAP实现WEB SERVICE[转载]
  6. sgu179 SGU起航!
  7. python学习之---- paramiko 模块
  8. Pycharm工具配置记录
  9. 某考试 T1 table
  10. iOS远程推送原理