并不对劲的splay
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的更多相关文章
- 并不对劲的bzoj1861: [Zjoi2006]Book 书架
传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...
- 并不对劲的bzoj1500: [NOI2005]维修数列
传送门-> 这题没什么好说的……小清新数据结构题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 其实这题应该口胡很容易.操作1,2,3,4,5就是普通的s ...
- 并不对劲的fhq treap
听说很对劲的太刀流不止会splay一种平衡树,并不对劲的片手流为了反驳他,并与之针锋相对,决定学学高端操作. 很对劲的太刀流-> 据说splay常数极大,但是由于只知道splay一种平衡树能对序 ...
- 并不对劲的LCT
LCT,是连猫树(link-cat-tree)的缩写.它是树链剖分和splay的结合版本. 由于有很多关于LCT的文章以及这并不是对劲的文章,并不对劲的人并不打算讲得太详细. 推荐:详细的LCT-&g ...
- BZOJ 1251: 序列终结者 [splay]
1251: 序列终结者 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3778 Solved: 1583[Submit][Status][Discu ...
- [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)
Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 文本:由0个或 ...
- splay最终模板
来自wjmzbmr的splay模板 #include<cstdio> #include<iostream> #include<algorithm> using na ...
- bzoj 3506 && bzoj 1552 splay
查最小值,删除,翻转... 显然splay啊... #include<iostream> #include<cstdio> #include<algorithm> ...
- 【splay】文艺平衡树 BZOJ 3223
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 ...
随机推荐
- Triangular Pastures (二维01背包)
描述Like everyone, cows enjoy variety. Their current fancy is new shapes for pastures. The old rectang ...
- CentOS7中,vnc分辨率设置。
使用geometry参数进行调整 例如,我们需要将分辨率调整到800x600 [root@secdb ~]# vncserver -geometry 800x600 New 'secdb:5 (roo ...
- 谢孟军:The State of Go | ECUG Con 精粹系列
本月 17 日,Go 1.8 版本火热发布.相较于以往的版本,Go 1.8 具体有哪些新的特性呢?想必这是不少 Gopher 们热切关注和讨论的问题.作为著名的Golang 布道者,Gopher Ch ...
- MTK andorid从底层到上层添加驱动
1 [编写linux驱动程序] 1.1 一.编写驱动核心程序 1.2 二.配置Kconfig 1.3 三.配置Makefile 1.4 四.配置系统的autoconfig 1.5 五.编译 2 [编写 ...
- 【2018 Multi-University Training Contest 2】
01: 02: 03: 04:https://www.cnblogs.com/myx12345/p/9394511.html 05: 06: 07:https://www.cnblogs.com/my ...
- Java使用IText(VM模版)导出PDF
Java使用IText(VM模版)导出PDF: public String createPDF(ProjectManageBase projectManageBase) { Map map = new ...
- LightOJ1094 - Farthest Nodes in a Tree(树的直径)
http://lightoj.com/volume_showproblem.php?problem=1094 Given a tree (a connected graph with no cycle ...
- loj6172 Samjia和大树(树形DP+找规律)
题目: https://loj.ac/problem/6172 分析: 首先容易得出这样的dp式子 然后发现后面那个Σ其实是两段区间,可以用总和减去中间一段区间表示,所以只要维护个前缀和就ok了 这样 ...
- FTRL (Follow-the-regularized-Leader)算法
Online gradient descent(OGD) produces excellent prediction accuracy with a minimum of computing reso ...
- Linux内核project导论——网络:Filter(LSF、BPF、eBPF)
概览 LSF(Linux socket filter)起源于BPF(Berkeley Packet Filter).基础从架构一致.但使用更简单.LSF内部的BPF最早是cBPF(classic).后 ...