【BZOJ 1269】文本编辑器
题目
这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:
Move k:将光标移动到第 \(k\) 个字符之后,如果 \(k=0\) , 将光标移到文本第一个字符之前。(注意是 cur = k 不是 cur += k)Insert n (换行) S:在光标后插入长度为n的字符串S,光标位置不变,\(n\ge 1\)。Delete n:删除光标后的 \(n\) 个字符,光标位置不变,\(n\ge 1\)。Rotate n:反转光标后的 \(n\) 个字符,光标位置不变,\(n\ge 1\)。Get:输出光标后的一个字符,光标位置不变。Prev:光标前移一个字符。Next:光标后移一个字符。
下面是几个定义:
- 文本:由0个或多个字符构成的序列。这些字符的 ASCII 码在闭区间 [32, 126] 内,也就是说,这些字符均为可见字符或空格。
- 光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。
- 文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。
编写一个程序:
- 建立一个空的文本编辑器。
- 从输入文件中读入一些操作指令并执行。
- 对所有执行过的 Get 操作,将指定的内容写入输出文件。
分析
发现一堆人的 Splay 是用 split 和 merge 做的, 然而我觉得既然写了 Splay, 为什么不用 Splay 呢?
试图掩盖我不会写这两操作的事实
重点在 Delete/Insert/Rotate 操作上.(下方 \(c\) 为光标的后一个字符的位置)
- Insert n S: 把 \(c - 1\) 和 \(c\) 分别旋转到根节点和根节点的右孩子, 此时根节点的右孩子的左孩子就代表了区间 \((c-1, c)\), 显然该区间为空, 用之前的建树去做就可以了.
- Delete n: 把 \(c - 1\) 和 \(c + n\) 旋转到根节点的右孩子, 此时根节点的右孩子的左孩子就代表了区间 \((c - 1, c + n )\), 即 \([c, c + n - 1]\), 随便删除即可.
- Rotate n: 把 \(c - 1\) 和 \(c + n\) 旋转到根节点的右孩子, 此时根节点的右孩子的左孩子就代表了区间 \((c - 1, c + n )\), 即 \([c, c + n - 1]\), 随便翻转即可.
然后随便写写就好了, 似乎也没有考虑讨论中说的毒瘤输入就过了...
代码
跑的似乎还很快? (\(1.8\ s\)).
#include <bits/stdc++.h>
#define fa(x) t[x].fa
#define siz(x) t[x].siz
#define val(x) t[x].val
#define tag(x) t[x].tag
#define child(x, y) t[x].child[y]
#define rt t[1].child[1]
const int kMaxSize = 2e6 + 5;
struct node {
int child[2], fa, siz; char val; bool tag;
} t[kMaxSize];
int cnt = 2;
inline void Cnct(int c, int f, int p) {fa(c) = f; child(f, p) = c;}
inline void Updata(int x) {siz(x) = siz(child(x, 0)) + siz(child(x, 1)) + 1;}
inline bool Which(int x) {return x == child(fa(x), 1);}
inline int NewNode(char val, int fa) {fa(cnt) = fa; val(cnt) = val; return cnt++;}
void PushTag(int x) {
if(tag(x)) {
child(x, 0) ^= child(x, 1) ^= child(x, 0) ^= child(x, 1);
tag(child(x, 0)) ^= 1; tag(child(x, 1)) ^= 1;
tag(x) = false;
}
}
void Rotate(int &x) {
int gfa = fa(fa(x)); bool p = Which(x), pfa = Which(fa(x));
Cnct(child(x, p ^ 1), fa(x), p); Cnct(fa(x), x, p ^ 1); Cnct(x, gfa, pfa);
Updata(child(x, p ^ 1)); Updata(x);
}
void Splay(int cur, int to = 1) {
for(; fa(cur) != to; Rotate(cur)) {
if(fa(fa(cur)) != to)
Which(cur) == Which(fa(cur)) ? Rotate(fa(cur)) : Rotate(cur);
}
}
void Build(int &cur, int fa, int l, int r, std::string &a) {
if(l <= r) {
int mid = (l + r) >> 1;
cur = NewNode(a[mid], fa);
Build(child(cur, 0), cur, l, mid - 1, a);
Build(child(cur, 1), cur, mid + 1, r, a);
Updata(cur);
}
}
void Output(int cur = rt) {
if(!cur) return;
PushTag(cur);
Output(child(cur, 0));
if(val(cur)) printf("%c", val(cur));
Output(child(cur, 1));
}
int FindKth(int k) {
for(int cur = rt, tot = 0; ; tot++) {
PushTag(cur);
if(k == siz(child(cur, 0)) + 1) return cur;
else if(k <= siz(child(cur, 0))) cur = child(cur, 0);
else k -= siz(child(cur, 0)) + 1, cur = child(cur, 1);
}
}
void Reverse(int x, int n) {
Splay(FindKth(x - 1)); Splay(FindKth(x + n), rt);
tag(child(child(rt, 1), 0)) ^= 1;
}
void Insert(int x, int ptr) {
Splay(FindKth(x - 1)); Splay(FindKth(x), rt);
Cnct(ptr, child(rt, 1), 0);
Updata(child(rt, 1)); Updata(rt);
}
void Delete(int x, int n) {
Splay(FindKth(x - 1)); Splay(FindKth(x + n), rt);
child(child(rt, 1), 0) = 0;
Updata(child(rt, 1)); Updata(rt);
}
using std::cout;
using std::cin;
int q, curt = 2; std::string s;
int main() {
std::ios::sync_with_stdio(false);
cin >> q;
s[1] = s[2] = 0;
Build(rt, 1, 1, 2, s);
while(q--) {
std::string opt, str; int n;
cin >> opt;
if(opt == "Move") {
cin >> n;
if(n == 0) curt = 2;
else curt = n + 2;
} else if(opt == "Insert") {
cin >> n;
cin.ignore();
getline(cin, str);
str = " " + str;
int ptr;
Build(ptr, 1, 1, n, str);
Insert(curt, ptr);
} else if(opt == "Delete") {
cin >> n;
Delete(curt, n);
} else if(opt == "Rotate") {
cin >> n;
Reverse(curt, n);
} else if(opt == "Get") {
int ptr = FindKth(curt);
Splay(ptr);
cout << val(ptr) << std::endl;
} else if(opt == "Prev") curt--;
else if(opt == "Next") curt++;
}
return 0;
}
【BZOJ 1269】文本编辑器的更多相关文章
- BZOJ 1269 文本编辑器 Splay
题目大意:维护一个文本编辑器,支持下列操作: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.翻转光标后的一段字符 5.输出光标后的一个字符 6.光标-- 7.光标 ...
- BZOJ 1269 文本编辑器editor(伸展树)
题意 https://www.lydsy.com/JudgeOnline/problem.php?id=1269 思路 伸展树(\(\text{splay}\))功能比较齐全的模板,能较好的体现 \( ...
- [AHOI 2006][BZOJ 1269]文本编辑器editor
好吧,我承认这是我用来刷随笔数的喵~ 这是一道 splay 裸题,但还是有想本傻 X 一样根本不会写 splay 的,于是乎又用 treap 水过了 splay 的常数我还是知道的,所以真是不知道那些 ...
- HYSBZ 1269文本编辑器 splay
比较基本的操作. #include<map> #include<queue> #include<stack> #include<cmath> #incl ...
- 【BZOJ】【1269】【AHOI2006】文本编辑器editor
Splay Splay序列维护的模板题了……为了便于处理边界情况,我们可以先插入两个空格当作最左端和最右端,然后……其实本题主要考察的就是Build.splay和Findkth这三个操作,我们可以实现 ...
- BZOJ 1269: [AHOI2006]文本编辑器editor( splay )
splay..( BZOJ 1507 题目基本相同..双倍经验 ) ------------------------------------------------------------------ ...
- 【BZOJ】1269: [AHOI2006]文本编辑器editor(Splay)
http://www.lydsy.com/JudgeOnline/problem.php?id=1269 这题RE2次啊,好不爽啊,我一直以为是splay的问题,其实是数组开小了......(我老犯这 ...
- BZOJ 1269: [AHOI2006]文本编辑器editor (splay tree)
1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1213 Solved: 454[Submit ...
- BZOJ 1269 【AHOI2006】 文本编辑器
题目链接:文本编辑器 这道题没啥好说的,直接上\(Splay\)就行了,板子题…… 但是我某个地方忘了下放标记导致调了一晚上 听说有个东西叫\(rope\)可以直接过?然而我并不会 保存一发板子: # ...
随机推荐
- react开发环境准备
使用reactjs,我们有两种方式 一种是通过script标签引入reactjs,这是一种比较古老的编码方式了, 如果我们的项目比较大,你会对项目js进行拆分,然后页面就会通过script标签加载很多 ...
- Angular 引用库
<!doctype html> <html ng-app> <head> <script src="http://code.angularjs.or ...
- conda清华镜像(TUNA)使用指南
Details: https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ TUNA 提供了 Anaconda 仓库的镜像,运行以下命令: conda c ...
- VS2012 Getting Started with Owin and Katana
参考地址:http://www.asp.net/aspnet/overview/owin-and-katana/getting-started-with-owin-and-katana 小提示: 该示 ...
- Entity Framework 五
连接情景中的CRUD操作: 连接场景中的CRUD操作是一项相当简单的任务,因为默认情况下,上下文会自动跟踪实体在其生命周期中发生的更改,前提是AutoDetectChangesEnabled为true ...
- android(eclipse)新手常见问题总结(一)
1:jdk无法更新 进入工具里面手动获取镜像资源 并且改为强制 2:报错:This version of the rendering library is more recent than you ...
- Java面向对象知道这些就够了
面向对象 面向对象是一种思维方式,相对于面向过程而言的. 面向过程在流程中关注动作执行的每一个细节 — 自己动手做 面向对象重点找这个对象,只要找到了对象,那么这个对象所具有的功能就能够被使用 — 找 ...
- CALayer创建图层(转)
一.添加一个图层 添加图层的步骤: 1.创建layer 2.设置layer的属性(设置了颜色,bounds才能显示出来) 3.将layer添加到界面上(控制器view的layer上) @int ...
- MySQL里面的锁
MySQL里面的锁可以分为:全局锁,表级锁,行级锁. 一.全局锁:对整个数据库实例加锁.MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL)这个命令可以 ...
- 带你解析Java类加载机制
目录 Java类加载机制的七个阶段 加载 验证 准备(重点) 解析 初始化(重点) 使用 卸载 实战分析 方法论 树义有话说 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如 ...