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. 73. Spring Boot注解(annotation)列表【从零开始学Spring Boot】

    [从零开始学习Spirng Boot-常见异常汇总] 针对于Spring Boot提供的注解,如果没有好好研究一下的话,那么想应用自如Spring Boot的话,还是有点困难的,所以我们这小节,说说S ...

  2. (4)主成分分析Principal Component Analysis——PCA

    主成分分析Principal Component Analysis 降维除了便于计算,另一个作用就是便于可视化. 主成分分析-->降维--> 方差:描述样本整体分布的疏密,方差越大-> ...

  3. 洛谷P1145 约瑟夫

    题目描述 n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人.现在有一圈人,k个好人站在一起,k个坏人站在一起.从第一个好人开始数数.你要确定一个最小 ...

  4. @Temporal()注解的使用

    数据库的字段类型有date.time.datetime而Temporal注解的作用就是帮Java的Date类型进行格式化,一共有三种注解值: 第一种:@Temporal(TemporalType.DA ...

  5. 尽量写出大家都能看懂的ReactJS入门教程

    个人感觉ReactJS相比于传统的JS框架还是挺有意思的,主要是它将JS代码和HTML代码完美的结合在了一起,有点jsp把java代码和html混在一起写的意思?但是它通过组件的形式实现了代码可复用, ...

  6. 新建一个基于vue.js+Mint UI的项目

    上篇文章里面讲到如何新建一个基于vue,js的项目(详细文章请戳用Vue创建一个新的项目). 该项目如果需要组件等都需要自己去写,今天就学习一下如何新建一个基于vue.js+Mint UI的项目,直接 ...

  7. 把excel导入到mysql中

    方法很多,不过建议你先看看mysql的开发文档,里面写的很详细的,如果你懒得看,可以看下面的 1.有个软件PHP Excel Parser Pro v4.2可以 2.可将Excel存成csv格式.然后 ...

  8. 【Java源码】集合类-优先队列PriorityQueue

    一.类继承关系 public class PriorityQueue<E> extends AbstractQueue<E> implements java.io.Serial ...

  9. HDU 1244 【DP】

    题意: 中文. 思路: 先初步处理,用give-take求出每个城市剩的钱. 求解问题转化成使得和不小于0的最长连续字串. 枚举起点,然后当该起点加的和为负时开始枚举下一起点.(这个状态的转移) 2W ...

  10. loj6165 一道水题(线性筛)

    题目: https://loj.ac/problem/6165 分析: 最直接的想法就是把1~n的所有数分解质因数,然后每个素数的幂取max 我们首先来看看一共可能有哪些素数? 实际上这些素因数恰好就 ...