题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269

  

Description

这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 

文本:由0个或多个字符构成的序列。这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。 编写一个程序: 建立一个空的文本编辑器。 从输入文件中读入一些操作指令并执行。 对所有执行过的GET操作,将指定的内容写入输出文件。

Input

输入文件中第一行是指令条数N,以下是需要执行的N个操作。除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。

Output

依次对应输入文件中每条GET指令的输出,不得有任何多余的字符。

Sample Input

10
Insert 13
Balanced eert
Move 2
Delete 5
Next
Insert 7
editor
Move 0
Get
Move 11
Rotate 4
Get

Sample Output

B
t

HINT

对输入数据我们有如下假定: MOVE操作不超过50 000个,INSERT、DELETE和ROTATE操作作的总个数不超过6 000,GET操作不超过20 000个,PREV和NEXT操作的总个数不超过20 000。 所有INSERT插入的字符数之和不超过2M(1M=1 024*1 024)。 DELETE操作、ROTATE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。 输入文件没有错误。

  用个全局变量记录cursor的位置,对于每个操作:

    Insert:先旋转,然后插入区间到根的右儿子的左子树。

    Delete:先旋转,然后删除根的右儿子的左子树。

    Rotate:区间标记,懒惰更新。

    Get:直接输出光标的后一个字符。

    其它的直接修改cursor的位置。。。

 //STATUS:C++_AC_1296MS_48380KB
#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
//typedef __int64 LL;
//typedef unsigned __int64 ULL;
//const
const int N=**+;
const int INF=0x3f3f3f3f;
const int MOD=,STA=;
//const LL LNF=1LL<<60;
const double EPS=1e-;
const double OO=1e15;
const int dx[]={-,,,};
const int dy[]={,,,-};
const int day[]={,,,,,,,,,,,,};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End #define Key_value ch[ch[root][1]][0]
int pre[N],ch[N][]; //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int sz[N],st[N]; //子树规模,内存池
int root,tot,top; //根节点,根节点数量,内存池容量
//题目特定数目
char key[N],s[N];
bool rev[N];
int n,m,cursor;
//debug部分copy from hh
void Treaval(int x) {
if(x) {
Treaval(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d rev = %2d key = %2c\n",x,ch[x][],ch[x][],pre[x],sz[x],rev[x],key[x]);
Treaval(ch[x][]);
}
}
void debug() {printf("%d\n",root);Treaval(root);}
//以上Debug
//新建一个结点
void NewNode(int &x,int fa,char c)
{
if(top)x=st[--top];
else x=++tot;
key[x]=c;
pre[x]=fa;
sz[x]=;
rev[x]=;
ch[x][]=ch[x][]=; //左右孩子为空
} void Push_Up(int x)
{
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
} void Push_Down(int x)
{
if(rev[x]){
rev[ch[x][]]^=;
rev[ch[x][]]^=;
swap(ch[x][],ch[x][]);
rev[x]=;
}
}
//旋转,kind为1为右旋,kind为0为左旋
void Rotate(int x,int kind)
{
int y=pre[x],z=pre[y];
Push_Down(y);
Push_Down(x); //先把y的标记向下传递,再把x的标记往下传递
//类似SBT,要把其中一个分支先给父节点
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
//如果父节点不是根结点,则要和父节点的父节点连接起来
if(z)ch[z][ch[z][]==y]=x;
pre[x]=z;
ch[x][kind]=y;
pre[y]=x;
Push_Up(y); //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
}
//Splay调整,将根为r的子树调整为goal
void Splay(int x,int goal)
{
int y,z,kind;
while(pre[x]!=goal){
//父节点即是目标位置,goal为0表示,父节点就是根结点
y=pre[x];
Push_Down(pre[y]);Push_Down(y);Push_Down(x); //设计到反转操作,要先更新,然后在判断!!
if(pre[y]==goal){
Rotate(x,ch[y][]==x);
}
else {
kind=ch[pre[y]][]==y;
//两个方向不同,则先左旋再右旋
if(ch[y][kind]==x){
Rotate(x,!kind);
Rotate(x,kind);
}
//两个方向相同,相同方向连续两次
else {
Rotate(y,kind);
Rotate(x,kind);
}
}
}
//更新根结点
Push_Up(x);
if(goal==)root=x;
} void RotateTo(int k,int goal)
{
int x=root;
Push_Down(x);
while(sz[ch[x][]]!=k){
if(sz[ch[x][]]>k)
x=ch[x][];
else {
k-=sz[ch[x][]]+;
x=ch[x][];
}
Push_Down(x);
}
Splay(x,goal);
}
//建树,中间结点先建立,然后分别对区间两端在左右子树建立
void BuildTree(int &x,int l,int r,int fa)
{
if(l>r)return;
int mid=(l+r)>>;
NewNode(x,fa,s[mid]);
BuildTree(ch[x][],l,mid-,x);
BuildTree(ch[x][],mid+,r,x);
Push_Up(x);
} void Init()
{
root=top=tot=;
ch[][]=ch[][]=sz[]=pre[]=rev[]=key[]=; NewNode(root,,);
NewNode(ch[root][],root,);
cursor=;
} void Insert(int len)
{
RotateTo(cursor,);
RotateTo(cursor+,root);
BuildTree(Key_value,,len-,ch[root][]);
Push_Up(ch[root][]);
Push_Up(root);
} void Delete(int n)
{
RotateTo(cursor,);
RotateTo(cursor+n+,root);
Key_value=;
Push_Up(ch[root][]);
Push_Up(root);
} void Rotate(int n)
{
RotateTo(cursor,);
RotateTo(cursor+n+,root);
rev[Key_value]^=;
} void Get()
{
int x=root,k=cursor+;
Push_Down(x);
while(sz[ch[x][]]!=k){
if(sz[ch[x][]]>k)
x=ch[x][];
else {
k-=sz[ch[x][]]+;
x=ch[x][];
}
Push_Down(x);
}
printf("%c\n",key[x]);
} int main()
{
// freopen("in.txt","r",stdin);
int i,j,k;
char op[];
while(~scanf("%d",&n))
{
Init();
while(n--){
scanf("%s",op);
if(op[]=='M'){
scanf("%d",&k);
cursor=k?k:;
}
else if(op[]=='I'){
scanf("%d",&k);
getchar();
gets(s);
Insert(k);
}
else if(op[]=='D'){
scanf("%d",&k);
Delete(k);
}
else if(op[]=='R'){
scanf("%d",&k);
Rotate(k);
}
else if(op[]=='G'){
Get();
}
else if(op[]=='P'){
cursor--;
}
else {
cursor++;
}
}
}
return ;
}

[AHOI2006]文本编辑器 Splay tree区间操作的更多相关文章

  1. BZOJ 1269: [AHOI2006]文本编辑器editor (splay tree)

    1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1213  Solved: 454[Submit ...

  2. BZOJ 1269: [AHOI2006]文本编辑器editor( splay )

    splay..( BZOJ 1507 题目基本相同..双倍经验 ) ------------------------------------------------------------------ ...

  3. 【BZOJ1269/1507】[AHOI2006]文本编辑器editor Splay

    [BZOJ1269][AHOI2006]文本编辑器editor Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目 ...

  4. 【bzoj1507】[NOI2003]Editor /【bzoj1269】[AHOI2006]文本编辑器editor Splay

    [bzoj1507][NOI2003]Editor 题目描述 输入 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中 ...

  5. BZOJ1269 [AHOI2006]文本编辑器editor 【82行splay】

    1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4633  Solved: 1782 [Sub ...

  6. AHOI2006文本编辑器editor

    1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1885  Solved: 683[Submit ...

  7. BZOJ 1269 文本编辑器 Splay

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

  8. BZOJ_1269&&1507_[AHOI2006]文本编辑器editor&&[NOI2003]Editor

    BZOJ_1269&&1507_[AHOI2006]文本编辑器editor&&[NOI2003]Editor 题意: 分析: splay模拟即可 注意1507的读入格式 ...

  9. [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)

    Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或 ...

随机推荐

  1. 全选与反选(dom与jquery比较)

    <html> <head> <title>全选或反选(dom)</title> <meta http-equiv="Content-Ty ...

  2. 【Mysql进阶技巧(1)】 MySQL的多表关联与自连接

    自连接 测试数据准备 CREATE TABLE `t2` ( `id` int(11) NOT NULL, `gid` char(1) DEFAULT NULL, `col1` int(11) DEF ...

  3. java中List集合及其遍历详解

    1. 首先List<E>集合继承与Collection<E>,是一个接口. ①  Collection (集合框架是JDK1.2版本出现的) ②   list:是有序的,元素可 ...

  4. python 包管理工具pip安装与使用

    pip是python的一个包管理工具,与之类似的工具还有easy_install.根据官网的说法 如果你的python版本在Python 2 >=2.7.9 or Python 3 >=3 ...

  5. objective C中数据持久化方式1--对象归档

    第一.数据持久化的方式: NSKeyedArchiver--对象归档 属性列表化(NSArray.NSDictionary.NSUserDefault) SQlite数据库.CoreData数据库 其 ...

  6. 【剑指offer】找出数组中出现一次的两个数

    2013-09-08 10:50:46 一个整型数组中,除了两个数字之外,其他数字都出现了2次,找出这两个只出现一次的数字,要求时间复杂度是O(N),空间复杂度是O(1). 小结: 任何数与0异或,结 ...

  7. Unable to open c

    1. Unable to open c:\Cadence\PSD_14.2\tools\capture\allegro.cfg for reading. Please correct the abov ...

  8. Windows 7/8 自带定时关机命令

    快捷键“Windows + R”,输入cmd打开cmd.exe程序,输入以下对应命令.   两种定时关机方式: 定时任务法 输入命令“at hh:mm shutdown -s”,Enter——添加了一 ...

  9. 弹出框页面中使用jquery.validate验证控件

    弹出框页面中使用jquery.validate验证控件有几个问题需要解决: 1,弹出框的提交事件完成后如何关闭弹出框页面? 2,提交不成功如何返回当前页? 3,如果知道验证事件成功? 之前笔者都是JS ...

  10. SSH2中memcached作为hibernate二级缓存

    一.安装memcached服务端 1. 下载memcached的windows稳定版,解压放某个盘下面,比如在c:\memcached2. 在CMD下输入 "c:\memcached\mem ...