【BZOJ】【1269】【AHOI2006】文本编辑器editor

Splay


  Splay序列维护的模板题了……为了便于处理边界情况,我们可以先插入两个空格当作最左端和最右端,然后……其实本题主要考察的就是Build、splay和Findkth这三个操作,我们可以实现一个splay(x,s)操作,使x结点旋转到s结点的下方(如果s为0则x旋转到根),这样可以方便地提取出要处理的区间。

  这份模板我还是比较满意的,因为写的没那么长……

  1 /**************************************************************
  2     Problem: 1269
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:1236 ms
  7     Memory:46220 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 1269
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 inline int getint(){
 23     int v=0,sign=1; char ch=getchar();
 24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 26     return v*sign;
 27 }
 28 const int N=2e6+1000,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31 int n;
 32 char s[N],v[N];
 33 int c[N][2],size[N],fa[N],root,tot;
 34 bool rev[N];
 35 #define L c[x][0]
 36 #define R c[x][1]
 37 void Push_up(int x){
 38     size[x]=size[L]+size[R]+1;
 39 }
 40 void Push_down(int x){
 41     if (rev[x]) {rev[L]^=rev[x]; rev[R]^=rev[x]; rev[x]=0; swap(L,R);}
 42 }
 43 void New_node(int &x,int f,int key){
 44     x=++tot;
 45     fa[x]=f; v[x]=key; 
 46     L=R=rev[x]=0;
 47     size[x]=1;
 48 }
 49 void Build(int &x,int f,int l,int r){
 50     if (l>r) return;
 51     int m=l+r>>1;
 52     New_node(x,f,s[m]);
 53     Build(L,x,l,m-1);
 54     Build(R,x,m+1,r);
 55     Push_up(x);
 56 }
 57 void Rotate(int x){
 58     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
 59     c[z][c[z][1]==y]=x;
 60     fa[x]=z; fa[y]=x; fa[c[x][r]]=y; 
 61     c[y][l]=c[x][r]; c[x][r]=y;
 62     Push_up(y);
 63 }
 64 int st[N],top;
 65 void Preview(int x){
 66     top=0; st[++top]=x;
 67     for(;fa[x];x=fa[x])
 68         st[++top]=fa[x];
 69     D(i,top,1) Push_down(st[i]);
 70 }
 71 void splay(int x,int s=0){
 72     int y;
 73     for(Preview(x);fa[x]!=s;Rotate(x))
 74         if ((fa[y=fa[x]])!=s) Rotate(c[y][1]==x^c[fa[y]][1]==y ? x : y);
 75     Push_up(x);
 76     if (!s) root=x;
 77 }
 78 int kth(int x,int k){
 79     if (rev[x]) Push_down(x);
 80     if (size[L]+1==k) return x;
 81     else if (size[L]>=k) return kth(L,k);
 82     else return kth(R,k-size[L]-1);
 83 }
 84 int main(){
 85 #ifndef ONLINE_JUDGE
 86     freopen("1269.in","r",stdin);
 87     freopen("1269.out","w",stdout);
 88 #endif
 89     n=getint();
 90     s[0]=s[1]=' ';
 91     Build(root,0,0,1);
 92     int x,now=1; char cmd[10];
 93     F(i,1,n){
 94         scanf("%s",cmd);
 95 //      cout <<"cmd: "<<cmd<<endl;
 96         if (cmd[0]=='I'){
 97             x=getint();//gets(s);
 98             gets(s);
 99             splay(kth(root,now));
100             splay(kth(root,now+1),root);
101             Build(c[c[root][1]][0],c[root][1],0,x-1);
102         }else if (cmd[0]=='M'){
103             now=getint()+1;
104         }else if (cmd[0]=='D'){
105             x=getint();
106             splay(kth(root,now)); splay(kth(c[root][1],x+1),root);
107             c[c[root][1]][0]=0; Push_up(c[root][1]); Push_up(root);
108         }else if (cmd[0]=='R'){
109             x=getint();
110             splay(kth(root,now)); splay(kth(c[root][1],x+1),root);
111             rev[c[c[root][1]][0]]^=1;
112         }else if (cmd[0]=='G'){
113             printf("%c\n",v[kth(root,now+1)]);
114         }else if (cmd[0]=='N'){
115             now++;
116         }else if (cmd[0]=='P'){
117             now--;
118         }
119     }
120     return 0;
121 }
View Code

1269: [AHOI2006]文本编辑器editor

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2273  Solved: 838
[Submit][Status][Discuss]

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操作不会把光标移动到非法位置。 输入文件没有错误。

Source

[Submit][Status][Discuss]
posted @ 2015-04-10 11:18  Tunix  阅读(238)  评论(0编辑  收藏  举报