题目链接

\(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧)

记录下光标的编号,维护就是\(Splay\)基操了。

另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r',我就被坑了。

#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
const int MAXINSERTLEN = 10000010;
struct SplayTree{
char val;
int ch[2], fa, size;
}t[MAXINSERTLEN];
char str[MAXINSERTLEN];
int num, root, n, len;
void pushup(int u){
t[u].size = t[t[u].ch[0]].size + t[t[u].ch[1]].size + 1;
}
void rotate(int x){
int y = t[x].fa; int z = t[y].fa; int k = t[y].ch[1] == x;
t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].fa = y;
t[x].ch[k ^ 1] = y; t[y].fa = x;
pushup(y); pushup(x);
}
void Splay(int x, int goal){
while(t[x].fa != goal){
int y = t[x].fa; int z = t[y].fa;
if(z != goal)
(t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
rotate(x);
}
if(goal == 0) root = x;
}
int build(int l, int r){
int id = ++num;
int mid = (l + r) >> 1;
t[id].val = str[mid];
if(mid > l){
t[id].ch[0] = build(l, mid - 1);
t[t[id].ch[0]].fa = id;
}
if(mid < r){
t[id].ch[1] = build(mid + 1, r);
t[t[id].ch[1]].fa = id;
}
pushup(id);
return id;
}
inline int findKth(int k){
int u = root;
while(1){
if(t[t[u].ch[0]].size >= k) u = t[u].ch[0];
else if(t[t[u].ch[0]].size == k - 1) return u;
else k -= t[t[u].ch[0]].size + 1, u = t[u].ch[1];
}
}
inline int next(int x, int mode){
Splay(x, 0);
int u = t[x].ch[mode]; mode ^= 1;
while(t[u].ch[mode]) u = t[u].ch[mode];
return u;
}
char opt;
int cur;
void print(int x){
if(t[x].ch[0]) print(t[x].ch[0]);
if(t[x].val != 1) printf("%c", t[x].val);
if(t[x].ch[1]) print(t[x].ch[1]);
}
int main(){
n = read();
root = cur = ++num; t[num].val = 1;
t[++num].fa = cur; t[num].val = 1;
t[cur].ch[1] = num; t[num].size = 1; t[cur].size = 2;
for(int i = 1; i <= n; ++i){
opt = getchar();
while(opt < 'A' || opt > 'Z') opt = getchar();
if(opt == 'I'){
len = read();
for(int i = 1; i <= len; ++i){
str[i] = getchar();
while(str[i] < 32 || str[i] > 126) str[i] = getchar();
}
Splay(cur, 0);
Splay(next(cur, 1), cur);
t[t[root].ch[1]].ch[0] = (len = build(1, len));
t[len].fa = t[root].ch[1];
Splay(t[t[root].ch[1]].ch[0], 0);
}
else if(opt == 'G'){
len = read();
Splay(cur, 0);
Splay(findKth(t[t[root].ch[0]].size + 2 + len), root);
print(t[t[root].ch[1]].ch[0]);
putchar('\n');
}
else if(opt == 'M')
cur = findKth(read() + 1);
else if(opt == 'P')
cur = next(cur, 0);
else if(opt == 'N')
cur = next(cur, 1);
else if(opt == 'D'){
len = read();
Splay(cur, 0);
Splay(findKth(t[t[root].ch[0]].size + 2 + len), root);
t[t[root].ch[1]].ch[0] = 0;
}
}
return 0;
}

【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)的更多相关文章

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

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

  2. 洛谷 P4008 [NOI2003]文本编辑器

    先推广一下 求赞 我们考虑这样的一个问题 给你一个序列,要求你支持插入,删除,查询单点值 如果用数组,查询O(1),插入删除最坏O(n) 如果用链表,插入删除O(1),查询最坏O(n) 如果用平衡树- ...

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

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

  4. [NOI2003] 文本编辑器 (splay)

    复制炸格式了,就不贴题面了 [NOI2003] 文本编辑器 Solution 对于光标的移动,我们只要记录一下现在在哪里就可以了 Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递 ...

  5. P4008 [NOI2003]文本编辑器

    思路 FHQ Treap的板子 用FHQ Treap维护中序遍历序列即可 然后数组开够! 代码 #include <cstdio> #include <cstring> #in ...

  6. [洛谷日报第62期]Splay简易教程 (转载)

    本文发布于洛谷日报,特约作者:tiger0132 原地址 分割线下为copy的内容 [洛谷日报第62期]Splay简易教程 洛谷科技 18-10-0223:31 简介 二叉排序树(Binary Sor ...

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

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

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

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

  9. BZOJ 1269 文本编辑器 Splay

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

  10. 洛谷.2042.[NOI2005]维护数列(Splay)

    题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...

随机推荐

  1. java — 值传递和引用传递

    在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用传递对象这一事实并不意味着 Java 应用程序按引用传递参数.参数可以是对象引用,而 Java ...

  2. JDK源码分析 – ArrayList

    ArrayList类的申明 ArrayList是一个支持泛型的,底层通过数组实现的一个可以存任意类型的数据结构,源码中的定义如下: public class ArrayList<E> ex ...

  3. 3dContactPointAnnotationTool开发日志(二三)

      smpl模型得是一个整体,于是我让子物体的选项卡的删除按钮消失,这样就不会删除不必要的东西然后产生奇怪现象:

  4. [转]Windows 7 蓝屏后获取 MEMORY.DMP 文件及注意事项

    转自:http://hi.baidu.com/guicomeon/item/d6753a177fc76f0f8fbde46a 系统默认会在 C:\Windows 目录下创建 MEMORY.DMP 文件 ...

  5. GetTickCount 和getTickCount

    GetTickCount:正常读取时间函数 getTickCount:不知道是什么鬼东东函数 都包含在windows.h中..运行出的结果天壤之别~~~

  6. C# 中的语法糖

    1.   using 代替了 try-catch-finally 因为之前是学 Java 的,在连接数据库或者进行文件读写操作时很自然的就使用了 try-catch-finally-,在 C# 中这样 ...

  7. 【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap

    题目描述 求一个序列所有的子区间,满足区间众数的出现次数大于区间长度的一半. 输入 第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型.数据类型的作用将在子任务中说明. 第二行n个用 ...

  8. BZOJ4028 HEOI2015公约数数列(分块)

    前缀gcd的变化次数是log的,考虑对每一种gcd查询,问题变为查询一段区间是否存在异或前缀和=x/gcd. 无修改的话显然可以可持久化trie,但这玩意实在没法支持修改.于是考虑分块. 对于每一块将 ...

  9. [SHOI2012]回家的路 最短路

    ---题面--- 题解: 吐槽:找了好久的错,换了n种方法,重构一次代码,,,, 最后发现,,, 数组开小了,其实一开始尝试开大了数组,但唯独没有尝试开大手写队列的数组.... 思路: 有两种方法,这 ...

  10. HDU.1285 确定比赛名次 (拓扑排序 TopSort)

    HDU.1285 确定比赛名次 (拓扑排序 TopSort) 题意分析 裸的拓扑排序 详解请移步 算法学习 拓扑排序(TopSort) 只不过这道的额外要求是,输出字典序最小的那组解.那么解决方案就是 ...