[NOI2003] 文本编辑器 (splay)
复制炸格式了,就不贴题面了
[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)的更多相关文章
- luogu P4008 [NOI2003]文本编辑器 splay 块状链表
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...
- 洛谷 P4008 [NOI2003]文本编辑器 解题报告
P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的 ...
- [NOI2003]文本编辑器 [Fhq Treap]
[NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b ...
- [AHOI2006]文本编辑器 Splay tree区间操作
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个 ...
- BZOJ 1269 文本编辑器 Splay
题目大意:维护一个文本编辑器,支持下列操作: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.翻转光标后的一段字符 5.输出光标后的一个字符 6.光标-- 7.光标 ...
- cogs 330. [NOI2003] 文本编辑器
★★★ 输入文件:editor2003.in 输出文件:editor2003.out 简单对比 时间限制:2 s 内存限制:128 MB [问题描述] 很久很久以前,DOS3.x的程序 ...
- 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)
题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...
- NOI2003 文本编辑器editor
1507: [NOI2003]Editor Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 1908 Solved: 738[Submit][Statu ...
- HYSBZ 1269文本编辑器 splay
比较基本的操作. #include<map> #include<queue> #include<stack> #include<cmath> #incl ...
随机推荐
- python七类之列表元组
列表 一.关键字: list lst = [ , , , , , , ,] lst = [1,2,3,4] 二.方法: 1.增加: . append( ) #追加,添加元素进列表最后 ls ...
- 洛谷(P1006 传纸条)
题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个mm行nn列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运 ...
- python2.7练习小例子(二十一)
21):1.题目:两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人.已抽签决定比赛名单.有人向队员打听比赛的名单.a说他不和x比,c说他不和x,z比,请编程序找出三队 ...
- springmvc+mybatis的两种配置和应用方式
一.不用写dao层实现的方式 1.导入依赖包,我的pom.xml文件配置如下: <project xmlns="http://maven.apache.org/POM/4.0.0&qu ...
- 【面试题】2018年最全Java面试通关秘籍第五套!
[面试题]2018年最全Java面试通关秘籍第五套! 原创 2018-04-26 徐刘根 Java后端技术 第一套:<2018年最全Java面试通关秘籍第一套!> 第二套:<2018 ...
- 2,理解JVM
一.内存管理: 1,内存结构: 栈和堆区别,栈是连续内存区,一般是2M单位,堆是不连续的链表.受限于虚拟内存,new时分配 PC寄存器.java栈.堆.方法区.本地方法区.运行常量池 java ...
- IDEA的terminal设置成Linux的终端一样
方式一:通过在Windows上安装Linux命令行工具 前提:需要安装Linux终端的命令行工具,并且最好可以安装 Gow (一个Windows下模拟Linux命令行工具集合,它集成了 Liunx 环 ...
- Python 3基础教程26-多行打印
本文来介绍多行打印.多行打印一般出现在欢迎界面,例如你玩过的游戏,第一个界面,很多文字显示. 我们随便打印几行,来模拟下这种多行打印情况. # 多行打印 print(''' 第一行内容 第二行内容 第 ...
- 面向对象 公有私有 property classmethod staticmethod
接口类(抽象类)--------就是一种规范 面向对象的私有与公有 对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的访问限制不 ...
- 基于Ubuntu搭建Linux路由器
开源,几乎代表了无所不能的意思,最近又因为它玩Hi了... 因业务发展,需要临时接入300MB的专线和千兆路由器,而公司现有的路由器却是百兆的,出于成本考虑,只能不想更换新的路由器,在网上查了一下可以 ...