复制炸格式了,就不贴题面了

[NOI2003] 文本编辑器

Solution

对于光标的移动,我们只要记录一下现在在哪里就可以了

Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递归建树,实际操作:把splay中的光标所在位置旋到根,光标后一位旋到根的下面,此时根的右节点的左子树是空的,直接插入我们所建的树的根即可

Delete:先找到我们要删除的是哪一段区间,把光标之前的点旋到根,终点之后的点旋到根的下面,直接扔掉根节点的右儿子的左子树即可

Get:也是找到区间递归中序输出就可以了

提示:为了防止越界,我在splay插入了两个换行符,保证题目输入不会出现就行,因此也要把光标初始值设为1

Code

#include<bits/stdc++.h>
#define il inline
#define rg register
#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b) using namespace std; const int N=1e6+10;
const int inf=2e9; void in(int &ans)
{
ans=0; int f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0', i=getchar();
ans*=f;
} int n,tot,m,now=1,root;
char s[N<<1]; struct Splay {
int f,size,ch[2];
Splay(){
size = ch[0] = ch[1] = 0;
}
char val;
}t[N<<1]; il bool get(int x) {
return t[t[x].f].ch[1]==x;
} il void up(int x) {
t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
} void rotate(int x) {
int f=t[x].f,gf=t[f].f;
int k1=get(x),k2=get(f);
t[gf].ch[k2]=x,t[x].f=gf;
t[f].ch[k1]=t[x].ch[k1^1],t[t[x].ch[k1^1]].f=f;
t[x].ch[k1^1]=f,t[f].f=x;
up(f); up(x);
} void splay(int x,int goal) {
while(t[x].f!=goal) {
int f=t[x].f,gf=t[f].f;
if(gf!=goal) get(x)^get(f)?rotate(x):rotate(f);
rotate(x);
}
if(!goal) root=x;
} int kth(int k) {
int u=root;
while(1) {
int y=t[u].ch[0];
if(k>t[y].size+1)
u=t[u].ch[1],k-=t[y].size+1;
else if(k<=t[y].size) u=y;
else return u;
}
} il void Move() {
in(now); now++;
} il int add(char c,int f) {
t[++tot].val=c; t[tot].size=1;
t[tot].f=f; return tot;
} int build(int f,int l,int r,char *s) {
int mid=l+r>>1;
char ch=s[mid];
int u=add(ch,f);//按中序遍历建树
if(l<mid) t[u].ch[0]=build(u,l,mid-1,s);
if(mid<r) t[u].ch[1]=build(u,mid+1,r,s);
up(u); return u;
} void Insert() {
int x; in(x); strcpy(s,"");
for(rg int i=1;i<=x;i++) {
char ch=getchar();
while(ch==10 || ch==13 || ch<32 || ch>126) ch=getchar();
s[i]=ch;
}
int l=kth(now);
int r=kth(now+1);
splay(l,0); splay(r,l);
t[t[root].ch[1]].ch[0]=build(t[root].ch[1],1,x,s);
up(t[root].ch[1]); up(root);
} void Delete() {
int x; in(x);
int l=kth(now),r=kth(now+x+1);//r=kth((now+x-1)+1+1)第一个+1指光标指到起点,因为实际上光标指的是起点-1所以要加回来,第二个+1指区间终点的后一个端点
splay(l,0); splay(r,l);
int u=t[root].ch[1];
t[u].ch[0]=0;
up(u); up(root);
} void out(int u) {
if(t[u].ch[0]) out(t[u].ch[0]);
if(t[u].val!='\n') putchar(t[u].val);
if(t[u].ch[1]) out(t[u].ch[1]);
} void Get() {
int x; in(x);
int l=kth(now),r=kth(now+x+1);
splay(l,0); splay(r,l);
out(t[t[root].ch[1]].ch[0]);
putchar('\n');
} int main()
{
//freopen("data.in", "r", stdin);
root=add('\n',0),t[root].ch[1]=add('\n',root);up(root);
in(n); char s[10];
while(n--) {
scanf("%s",s);
if(s[0]=='M') Move();
if(s[0]=='I') Insert();
if(s[0]=='D') Delete();
if(s[0]=='G') Get();
if(s[0]=='P') now--;
if(s[0]=='N') now++;
}
return 0;
}

博主蒟蒻,随意转载.但必须附上原文链接

http://www.cnblogs.com/real-l/

[NOI2003] 文本编辑器 (splay)的更多相关文章

  1. luogu P4008 [NOI2003]文本编辑器 splay 块状链表

    LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...

  2. 洛谷 P4008 [NOI2003]文本编辑器 解题报告

    P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的 ...

  3. [NOI2003]文本编辑器 [Fhq Treap]

    [NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b ...

  4. [AHOI2006]文本编辑器 Splay tree区间操作

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个 ...

  5. BZOJ 1269 文本编辑器 Splay

    题目大意:维护一个文本编辑器,支持下列操作: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.翻转光标后的一段字符 5.输出光标后的一个字符 6.光标-- 7.光标 ...

  6. cogs 330. [NOI2003] 文本编辑器

    ★★★   输入文件:editor2003.in   输出文件:editor2003.out   简单对比 时间限制:2 s   内存限制:128 MB [问题描述] 很久很久以前,DOS3.x的程序 ...

  7. 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)

    题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...

  8. NOI2003 文本编辑器editor

    1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1908  Solved: 738[Submit][Statu ...

  9. HYSBZ 1269文本编辑器 splay

    比较基本的操作. #include<map> #include<queue> #include<stack> #include<cmath> #incl ...

随机推荐

  1. python七类之列表元组

    列表 一.关键字:  list  lst = [ , , , , , , ,] lst = [1,2,3,4] 二.方法: 1.增加:​ . append( ) #追加​​​,添加元素进列表最后 ls ...

  2. 洛谷(P1006 传纸条)

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个mm行nn列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运 ...

  3. python2.7练习小例子(二十一)

        21):1.题目:两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人.已抽签决定比赛名单.有人向队员打听比赛的名单.a说他不和x比,c说他不和x,z比,请编程序找出三队 ...

  4. springmvc+mybatis的两种配置和应用方式

    一.不用写dao层实现的方式 1.导入依赖包,我的pom.xml文件配置如下: <project xmlns="http://maven.apache.org/POM/4.0.0&qu ...

  5. 【面试题】2018年最全Java面试通关秘籍第五套!

    [面试题]2018年最全Java面试通关秘籍第五套! 原创 2018-04-26 徐刘根 Java后端技术 第一套:<2018年最全Java面试通关秘籍第一套!> 第二套:<2018 ...

  6. 2,理解JVM

      一.内存管理:   1,内存结构: 栈和堆区别,栈是连续内存区,一般是2M单位,堆是不连续的链表.受限于虚拟内存,new时分配 PC寄存器.java栈.堆.方法区.本地方法区.运行常量池 java ...

  7. IDEA的terminal设置成Linux的终端一样

    方式一:通过在Windows上安装Linux命令行工具 前提:需要安装Linux终端的命令行工具,并且最好可以安装 Gow (一个Windows下模拟Linux命令行工具集合,它集成了 Liunx 环 ...

  8. Python 3基础教程26-多行打印

    本文来介绍多行打印.多行打印一般出现在欢迎界面,例如你玩过的游戏,第一个界面,很多文字显示. 我们随便打印几行,来模拟下这种多行打印情况. # 多行打印 print(''' 第一行内容 第二行内容 第 ...

  9. 面向对象 公有私有 property classmethod staticmethod

    接口类(抽象类)--------就是一种规范 面向对象的私有与公有 对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的访问限制不 ...

  10. 基于Ubuntu搭建Linux路由器

    开源,几乎代表了无所不能的意思,最近又因为它玩Hi了... 因业务发展,需要临时接入300MB的专线和千兆路由器,而公司现有的路由器却是百兆的,出于成本考虑,只能不想更换新的路由器,在网上查了一下可以 ...