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

并不对劲的splay的更多相关文章

  1. 并不对劲的bzoj1861: [Zjoi2006]Book 书架

    传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...

  2. 并不对劲的bzoj1500: [NOI2005]维修数列

    传送门-> 这题没什么好说的……小清新数据结构题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 其实这题应该口胡很容易.操作1,2,3,4,5就是普通的s ...

  3. 并不对劲的fhq treap

    听说很对劲的太刀流不止会splay一种平衡树,并不对劲的片手流为了反驳他,并与之针锋相对,决定学学高端操作. 很对劲的太刀流-> 据说splay常数极大,但是由于只知道splay一种平衡树能对序 ...

  4. 并不对劲的LCT

    LCT,是连猫树(link-cat-tree)的缩写.它是树链剖分和splay的结合版本. 由于有很多关于LCT的文章以及这并不是对劲的文章,并不对劲的人并不打算讲得太详细. 推荐:详细的LCT-&g ...

  5. BZOJ 1251: 序列终结者 [splay]

    1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3778  Solved: 1583[Submit][Status][Discu ...

  6. [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)

    Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或 ...

  7. splay最终模板

    来自wjmzbmr的splay模板 #include<cstdio> #include<iostream> #include<algorithm> using na ...

  8. bzoj 3506 && bzoj 1552 splay

    查最小值,删除,翻转... 显然splay啊... #include<iostream> #include<cstdio> #include<algorithm> ...

  9. 【splay】文艺平衡树 BZOJ 3223

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

随机推荐

  1. xtu summer individual 2 E - Double Profiles

    Double Profiles Time Limit: 3000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

  2. Android CircleImageView圆形ImageView

     Android CircleImageView圆形ImageView CircleImageView是github上一个第三方开源的实现圆形ImageView的项目.其在github上的项目主页 ...

  3. 【转】关于大型网站技术演进的思考(二十一)--网站静态化处理—web前端优化—下【终篇】(13)

    本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了一个事业部,不过该企业把这个事业部里的人事成本,系统运维成本特别 ...

  4. hdu 1564水题Play a game

    #include<stdio.h> int main() {  int n;  while(scanf("%d",&n),n) {   n=n*n-1;   i ...

  5. 搭建双塔(vijos 1037)

    描述 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔. Mr. F有N块水晶,每块 ...

  6. Milking Time---poj3616

    Description Bessie is such a hard-working cow. In fact, she is so focused on maximizing her producti ...

  7. Generate Parentheses(组合,回溯)

    Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...

  8. 2017多校Round3(hdu6056~hdu6066)

    补题进度:7/11 1001 待填坑 1002 待填坑 1003(set) 题意: 给定长度为n(n<=5e5)的数组(是n的一个排列)和一个整数k(k<=80),f[l,r]定义为区间[ ...

  9. 【.Net Core 学习系列】-- EF Core 实践(Code First)

    一.开发环境: VS2015, .Net Core 1.0.0-preview2-003156 二解决方案: 新建项目: File --> New --> Project -->   ...

  10. ubuntu安装ftp环境

    ubuntu安装ftp环境 安装: apt install vsftpd 启动: service vsftpd start 查看状态: service vsftpd status root登录: vi ...