【BZOJ1269】[AHOI2006] 文本编辑器editor(Splay)
大致题意: 让你维护一个字符串,有插入字符串、删除区间、反转区间和输出单个字符操作。
\(Splay\)
这应该是一道比较简单的\(Splay\)题(虽然因为各种细节我调了很久)。
我们可以考虑用一个变量\(k\)来记录光标的位置,然后用\(Splay\)维护。
关于用\(Splay\)维护区间详见这篇博客中关于维护序列的部分:简析平衡树(三)——浅谈Splay。
下面是对各操作实现的简单概括,具体实现见代码。
\(Move\)操作
更新\(k\)即可。
\(Insert\)操作
首先,将给你的字符串先建成一棵树,记其根为\(p\)。
然后,将第\(k-1\)个节点\(Splay\)到根,第\(k+1\)个节点\(Splay\)到根的右儿子,此时根节点的右儿子的左儿子就是第\(k\)个节点。
再就可以将\(p\)作为这个节点的右儿子了(千万注意,要先\(PushDown\)这个节点再操作,不然会旋转子树)。
但还要注意维护\(Size\),一个简单的方法是将\(p\)直接旋到根即可。
\(Delete\)操作
设删除的区间为\([l,r]\)。
则将第\(l-1\)个节点\(Splay\)到根,第\(r+1\)个节点\(Splay\)到根的右儿子,然后将根节点的右儿子的左儿子赋值为\(0\),并\(PushUp\)根节点的右儿子和根即可。
\(Rotate\)操作
实际上我感觉这个操作应叫\(Reverse\)操作。。。
和\(Delete\)操作差不多吧,只不过是把清零改成翻转,且不用\(PushUp\)罢了。
\(Get\)操作
将第\(k-1\)个节点\(Splay\)到根,第\(k+1\)个节点\(Splay\)到根的右儿子,此时根节点的右儿子的左儿子就是第\(k\)个节点。
返回其权值即可。
\(Prev\)操作
\(--k\)即可。
\(Next\)操作
\(++k\)即可。
关于此题的一些坑点
- 这可能是我的\(Splay\)的问题,一开始在序列的前后需各加两个而不是一个字符作为辅助字符。
- 数据有毒。虽然题目中的合法字符集不包括回车符,但数据里的确有,所以读入字符串时应读入\(n\)个字符。
- 依然是回车的问题,如果查询时得到的答案是回车符,则不能再换行。
- 不要漏掉任何一个\(PushUp\)和\(PushDown\),牢记:多写不会\(WA\)!这点常数不会\(TLE\)!
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define swap(x,y) (x^=y^=x^=y)
#define hl_AK_NOI true
using namespace std;
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn(x) (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn(x)+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
I void reads(string& x) {x="";W(isspace(c=tc()));W(x+=c,!isspace(c=tc())&&~c);}
I void readc(char& x) {x=tc();}
}F;
class Splay//Splay
{
private:
#define PU(x) (O[x].Sz=O[O[x].S[0]].Sz+O[O[x].S[1]].Sz+1)//上传子树信息,更新Size
#define Re(x) (swap(O[x].S[0],O[x].S[1]),O[x].R^=1)//翻转一个子树
#define PD(x) (O[x].R&&(Re(O[x].S[0]),Re(O[x].S[1]),O[x].R=0))//下传翻转标记
#define Wh(x) (O[O[x].F].S[1]==x)//查询是父节点的哪一个儿子
#define Co(x,y,d) (O[O[x].F=y].S[d]=x)//连接两个节点
#define Sp(x,y) (S(GV((x)-1),rt),S(GV((y)+1),O[rt].S[1]),O[O[rt].S[1]].S[0])//抠出一个区间
static const int SZ=2097152;int rt,tot;struct node {char V;int Sz,R,F,S[2];}O[SZ+5];
I void Ro(CI x,int& k)//Rotate操作
{
RI f=O[x].F,p=O[f].F,d=Wh(x);PD(p),PD(f),PD(x),(f^k?O[p].S[Wh(f)]:k)=x,
O[x].F=p,Co(O[x].S[d^1],f,d),Co(f,x,d^1),PU(f),PU(x);
}
I void S(CI x,int& k) {RI f;W(x^k) f=O[x].F,f^k&&(Ro(Wh(x)^Wh(f)?x:f,k),0),Ro(x,k);PU(x);}//Splay操作
I int GV(RI rk)//求出排名为k的节点的编号
{
RI x=rt;W(hl_AK_NOI)//hl_AK_NOI=true
{
if(PD(x),O[O[x].S[0]].Sz>=rk) x=O[x].S[0];//如果左儿子Size大于等于rk,说明答案在左子树(记得先PushDown)
else if(rk-=O[O[x].S[0]].Sz+1) x=O[x].S[1];//如果rk减去左儿子与当前节点的Size和后大于0,就说明答案在右子树
else return x;//否则,说明答案在当前节点
}
}
public:
I void Init() {rt=Build(0,3,"€€€€");}//初始化(好不容易找到的一个既能显示又不在合法字符集内的字符)
int Build(CI l,CI r,Con string& s)//建树
{
RI x=++tot,t,mid=l+r>>1;O[x].V=s[mid],//二分
l^mid&&(t=Build(l,mid-1,s),Co(t,x,0)),r^mid&&(t=Build(mid+1,r,s),Co(t,x,1));//处理两个儿子
return PU(x),x;//返回当前节点编号
}
I void Insert(CI x,CI p) {RI k=Sp(x+2,x+2);PD(k),Co(p,k,1),S(p,rt);}//插入
I void Delete(CI x,CI y) {Sp(x+2,y+2)=0,PU(O[rt].S[1]),PU(rt);}//删除
I void Rever(CI x,CI y) {RI k=Sp(x+2,y+2);Re(k);}//翻转
I char Query(CI x) {return O[Sp(x+2,x+2)].V;}//询问
}S;
int main()
{
RI Qtot,i,x,k=0;Reg string op,s;Reg char c;S.Init(),F.read(Qtot);W(Qtot--)
{
F.reads(op);switch(op[0])
{
case 'M':F.read(x),k=x;break;//移动光标
case 'I'://插入
for(F.read(x),s="",i=0;i^x;++i) F.readc(c),s+=c;//注意应读入n个字符
S.Insert(k,S.Build(0,x-1,s));
break;
case 'D':F.read(x),S.Delete(k+1,k+x);break;//删除
case 'R':F.read(x),S.Rever(k+1,k+x);break;//翻转
case 'G':putchar(c=S.Query(k+1)),c^'\n'&&putchar('\n');break;//询问,注意特判回车
case 'P':--k;break;case 'N':++k;break;//前移和后移
}
}return 0;
}
【BZOJ1269】[AHOI2006] 文本编辑器editor(Splay)的更多相关文章
- [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)
Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 文本:由0个或 ...
- [BZOJ1269] [AHOI2006] 文本编辑器editor (splay)
Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 文本:由0个或多 ...
- 【BZOJ1269/1507】[AHOI2006]文本编辑器editor Splay
[BZOJ1269][AHOI2006]文本编辑器editor Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目 ...
- 【bzoj1507】[NOI2003]Editor /【bzoj1269】[AHOI2006]文本编辑器editor Splay
[bzoj1507][NOI2003]Editor 题目描述 输入 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中 ...
- BZOJ1269 [AHOI2006]文本编辑器editor 【82行splay】
1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4633 Solved: 1782 [Sub ...
- BZOJ 1269: [AHOI2006]文本编辑器editor( splay )
splay..( BZOJ 1507 题目基本相同..双倍经验 ) ------------------------------------------------------------------ ...
- Bzoj1269 [AHOI2006]文本编辑器editor
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3678 Solved: 1380 Description 这些日子,可可不和卡卡一起玩了,原来可可正 ...
- BZOJ1269——[AHOI2006]文本编辑器editor
1.题意:各种splay操作,一道好的模板题2333 2.分析:splay模板题,没啥解释QAQ #include <stack> #include <cstdio> #inc ...
- 【rope】bzoj1269 [AHOI2006]文本编辑器editor
维护一个字符串,支持以下操作: 主要就是 成段插入.成段删除.成段翻转.前两个操作很好通过rope实现.第三个操作也不难,维护两个rope,一个正向,一个反向,翻转时swap一下就行了. ro ...
- BZOJ 1269: [AHOI2006]文本编辑器editor (splay tree)
1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1213 Solved: 454[Submit ...
随机推荐
- Paw —— 比Postman更舒服的API利器
特点: 颜值高本地应用,流畅有收藏夹,管理请求可使用环境变量.比如用来一键切换开发环境请求和线上环境请求.即不同环境的同个接口只有host不一样,其它都是一样的,所以就把host抽离出来弄成一个环境变 ...
- GC:并行回收CMS详解
CMS详解 https://www.cnblogs.com/ggjucheng/p/3977612.html CMS默认不回收Perm, 需要加参数 +CMSPermGenSweepingEnable ...
- python安装包的时候报错
python安装包的时候报错 今天兴致勃勃的安装了一个paramiko包,过程很顺利,但是到结尾的时候报错,这就让人不爽了. 所以呢,需要安装一个名为python-dev的软件包. 该软件包包括头文件 ...
- 使用nrm解决npm下载包慢的问题!
nrm的安装使用 作用:提供了一些最常用的NPM包镜像地址,能够让我们快速的切换安装包时候的服务器地址: 什么是镜像:原来包刚一开始是只存在于国外的NPM服务器,但是由于网络原因,经常访问不到,这时候 ...
- RTT之内核服务函数
一 延时函数: rt_thread_delay(t) //调用时进入系统调度. rt_kprintf()函数在kservice.c中实现,如果不使用设备驱动,则由自定义函数void rt_hw_con ...
- SQL事务的四种隔离级别
1未提交读(Read uncommitted):完全不锁表,所以会出现脏数据.2提交读(Read committed):1.事务1中update才锁表,可以select到最新数据. 事务2select ...
- [编程题] 小易喜欢的数列 dp
https://www.nowcoder.com/question/next?pid=6291726&qid=112729&tid=12736753 [编程题] 小易喜欢的数列 时间限 ...
- SharePreferences的用法
1.创建 sharepreferences的方法: 首先创建该对象: 例如:(注意现在后面的模式7.0可以使用的只有 MODE_PRIVATE,其他全过时了 ) SharedPreferences s ...
- Kure讲HTML_HTML界面结构
1.HTML界面结构: 通常通过html开发的网页,它有一个自己固定的书写格式(类似于写信的时候也有固定的格式) <!-- DOCTYPE用来告诉浏览器用当前html文档是用html的哪个版本编 ...
- hbase常识及habse适合什么场景
当我们对于数据结构字段不够确定或杂乱无章很难按一个概念去进行抽取的数据适合用使用什么数据库?答案是什么,如果我们使用的传统数据库,肯定留有多余的字段,10个不行,20个,但是这个严重影响了质量.并且如 ...