splay总结
以此文纪念人生首次竞赛大选
这里主要讲一讲splay的区间操作,我讲的是指针实现,程序的效率可能比较低,更偏重代码的可读可写性,语言风格不是很优美有效,不喜勿喷
零、初始化结构体
1)这里主要是初始化结构体,记得先生成一个null节点指针,代表一切未使用的、未开发的节点,root也先赋值为null
2)结构体成员:有几个指针,如父亲(没有也可以,只不过令splay失去一些平衡树的功能),左右儿子,这里用数组记录,下标为0,1,方便我们操作
有几个需要维护的域,如size,子树和根的大小(包括重复节点),mul,重复节点的计数器,rev,区间翻转标记,一层一层地传,addnum,区间加的标记,cov,区间覆盖标记
3)结构体函数:可以自己写一个构造函数,可以声明后在结构体外写,就可以用null指针了,但最好是在结构体外写一个newnode,这样更清晰且更灵活
4)下传函数(relax/pushdown):
DEBUG:这里注意每次下传rev时,要马上实现交换左右儿子
DEBUG:这里注意所有的,如max域和sum域也要进行区间加操作
主要实现了区间加、区间覆盖、区间翻转的标记的下传
DEBUG:记得从上到下pushdown
5)更新函数(pushup/update):
根据需要看max域从儿子传上来挑最大,size域加儿子的size和自己的mul,不考虑重复时就用1代替
DEBUG:记得从下到上pushup
一、插入/构造
DEBUG:一下所有的涉及改动的操作记得用址传,不然会出大事哦
1)区间插入,先说进阶的,我们直接对构造一棵平衡树后,将所需区间伸展至根节点右儿子的左儿子处,将构造号的树塞到那里
DEBUG:这里注意塞完树以后记得更新根节点右儿子和根节点的维护域
2)单点插入,和区间一样,伸展所需位置,插入即可
DEBUG:一样滴,这里注意塞完树以后记得更新根节点右儿子和根节点的维护域
(似乎最后将插入的区间做一次splay可以提高效率)
二、删除
主要讲讲区间吧,先把区间伸展到指定位置,我是用递归实现整颗子树的删除的,先递归非空左右儿子,后用系统关键字delete删除当前指针
DEBUG:这里一样要更新有关节点,即pushup
三、旋转
这就不需要多说,平衡树的基础知识
我的函数是指定当前节点,将其对父亲旋转
DEBUG:注意下操作顺序
先提取出父亲的指针,再把当前节点接到父亲的位置
此后把当前和节点异侧的儿子接到父亲连当前节点的位置
之后把父亲接到这个儿子的位置
记得更新一下
四、splay函数/伸展操作
简化一下,主要分了三种情况
第一,当前节点的爷爷是目标节点,直接旋转当前节点
否则
第二,当前节点和父亲不在同侧,旋转当前节点两次
第三,当前节点和父亲在同侧,就先旋转父亲,再旋转当前节点
DEBUG:在函数结尾记得对当前节点进行更新操作,因为旋转函数的更新可能不完全
五、求第k个
这个没什么好说的,我是用循环实现的,非递归
可能此后还有一些进阶操作,这里就不提及了,那不是总结可以穷尽的
最后放个板
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define mid ((x>>1)+(y>>1)+(x&y&1))
using namespace std;
const int N = 1e4+;
const int inf = ~0U>>;
struct nt{
nt*ch[],*p; int k,size; int add;bool rev; bool d(){
return this==p->ch[];
} void setc(nt*c,int d){
ch[d]=c;
c->p=this;
} void addIt(int ad){
k+=ad;
add+=ad;
} void revIt(){
rev^=;
swap(ch[],ch[]);
} void pu(){
size=+ch[]->size+ch[]->size;
} void relax(){
if(rev)
ch[]->revIt(),
ch[]->revIt(),
rev=;
if(add)
ch[]->addIt(add),
ch[]->addIt(add),
add=;
}
}; nt*null=new nt();
nt*root=null;
int a[N]; nt*make(nt*p,int k){
nt*now=new nt();
now->size=;
now->k=k;
now->p=p;
now->ch[]=now->ch[]=null;
return now;
} void rot(nt*&o){
nt*p=o->p;
p->relax();
o->relax();
bool d=o->d();
p->p->setc(o,p->d());
p->setc(o->ch[!d],d);
o->setc(p,!d);
p->pu();o->pu();
if(p==root)root=o;
} void splay(nt*o,nt*p){
while(o->p!=p)
if(o->p->p==p)
rot(o);
else
o->d()^o->p->d()?(rot(o),rot(o)):(rot(o->p),rot(o));
o->pu();
} nt*build(int x,int y){
if(x>y)return null;
nt*o=make(o,a[mid]);
o->setc(build(x,mid-),);
o->setc(build(mid+,y),);
o->pu();
return o;
} void del(nt*&o){
if(o->ch[]!=null)del(o->ch[]);
if(o->ch[]!=null)del(o->ch[]);
delete o;
} nt*kth(int k){
for(nt*o;;){
o->relax();
if(k<=o->ch[]->size)
o=o->ch[];
else{
k-=o->ch[]->size+;
if(!k)return o;
o=o->ch[];
}
}
} int main(){
int n;
/*
*a=read(1~n)
*/
root=build(,n+);
root->p=null;
/*
insert l,r?
*a=read(1~r)
splay(kth(l+1),null)
splay(kth(l+2),root)
root->ch[1]->setc(build(1,r),0)
root->ch[1]->pu()
root->pu()
*/
return ;
}
完结,撒花~~~
splay总结的更多相关文章
- 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 ...
- 【填坑】bzoj3224 splay裸题
人生第一道splay不出所料是一道裸题,一道水题,一道2k代码都不到的题 #include <cstdio> ,n,p,q; ],c[][],size[],sp[]; void rot(i ...
- BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6243 Solved: 2007[Submit] ...
- BZOJ1500: [NOI2005]维修数列[splay ***]
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 12278 Solved: 3880[Submit][Statu ...
- HDU1890 Robotic Sort[splay 序列]
Robotic Sort Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- BZOJ3223: Tyvj 1729 文艺平衡树 [splay]
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3595 Solved: 2029[Submit][Sta ...
随机推荐
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3364728.html 我前两天写过一篇博客<Android使用Fragment来 ...
- Servlet基础(三) Servlet的多线程同步问题
Servlet基础(三) Servlet的多线程同步问题 Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率. 由于Servlet/JSP默认是以多线程模式执行的, ...
- 简单粗暴的对android so文件加壳,防止静态分析
转载自http://bbs.pediy.com/showthread.php?t=191649 以前一直对.so文件加载时解密不懂,不了解其工作原理和实现思路.最近翻看各种资料,有了一些思路.看到论坛 ...
- net2.0对于递归变量的处理方式不同引发的递归问题
同样的代码,用NET2.0执行产生的效果与其它框架使用的不同,导致报错. 认真查找原因后发现该程序的编写人员隐式的使用了一个公共变量,使之在递归过程中不断的被改写,使得1次递归后就破坏了原来的循环体, ...
- windows 常用命令
1 Services.msc 在运行输入 启动所有安装程序配置
- 用最简单话概括SSH三框架
Hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL语句. Struts是用来做应用层的,他它负责调用业务逻辑serivce层,所以S ...
- github邮箱验证技巧
申请的github账号,绑定邮箱之后才能创建库,而反复几次的发送邮件均为收到验证邮件,猜测有两个原因: 1.腾讯邮件服务器屏蔽了github的来信 (腾讯不会这么狭隘的,×) 2.自己邮箱的域名黑名单 ...
- 基于微软平台IIS/ASP.NET开发的大型网站有哪些?
首先说明一下,本文绝不是要说Microsoft平台多么好,多么牛.只是要提醒一些LAMP/Java平台下的同志们,微软平台不至于像你们说的,和想象的那么不堪!只是你们自己不知道而已.同时,也希望广大M ...
- servlet 学习(二)
一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...
- 迪杰斯特拉算法——PAT 1003
本文主要是将我对于我对于迪杰斯特拉算法的理解写出来,同时通过例题来希望能够加深对于算法的理解,其中有错误的地方希望大家指正. 迪杰斯特拉算法 我将这个算法理解成一个局部到整体的算法,这个方法确实越研究 ...