【BZOJ1269】文本编辑器-Splay

维护一个字符串,支持插入,删除,翻转一段区间。

可以用Splay来做,光标位置可以用一个全局变量pos代替,移动光标操作就相应的修改pos就行了。

插入删除都是Splay基本操作,翻转区间需要打标记,下传的时候交换左右儿子就好了。

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 
  5 using namespace std;
  6 
  7 const int N = (1<<21) + 5;
  8 
  9 int m, k;
 10 char s[N], op[10];
 11 
 12 struct SplayTree{
 13     #define ls son[x][0]
 14     #define rs son[x][1]
 15     #define key_val son[son[rt][1]][0]
 16     
 17     int sz, rt, son[N][2], pre[N];
 18     char val[N];
 19     inline void init(){
 20         pos = 1;
 21         rt = sz = 0;
 22         Newnode(rt,0,'$');
 23         Newnode(son[rt][1],rt,'$');
 24         size[rt] = 2;
 25     }
 26     inline void Newnode( int &x, int y, char w ){
 27         x = ++sz;
 28         pre[x] = y;
 29         val[x] = w;
 30         size[x] = 1;
 31         ls = rs = 0;
 32     }
 33     inline void Build( int &x, int y, int l, int r ){
 34         if ( l > r ) return;
 35         int mid = (l+r)>>1;
 36         Newnode( x,y,str[mid] );
 37         Build( ls,x,l,mid-1 );
 38         Build( rs,x,mid+1,r );
 39         pushup(x);
 40     }
 41     inline void pushup( int x ){
 42         size[x] = size[ls] + size[rs] + 1;
 43     }
 44     inline void pushdown( int x ){
 45         if ( !rev[x] ) return;
 46         swap( ls,rs );
 47         rev[ls] ^= 1;
 48         rev[rs] ^= 1;
 49         rev[x] = 0;
 50     }
 51     inline void Link( int x, int y, int d ){
 52         pre[x] = y; son[y][d] = x;
 53     }
 54     inline void Rotate( int x, int d ){
 55         int y = pre[x], z = pre[y];
 56         pushdown(y);pushdown(x);
 57         Link( son[x][d],y,!d );
 58         pre[x] = pre[y];
 59         if ( z ) Link( x,z,son[z][1]==y );
 60         Link( y,x,d );
 61         pushup(y);
 62     }
 63     inline void Splay( int x, int s ){
 64         pushdown(x);
 65         while ( pre[x] != s ){
 66             int y = pre[x], z = pre[y];
 67             if ( z != s ){
 68                 int d = (son[z][0]==y);
 69                 if ( son[y][d] == x ) Rotate(x,!d),Rotate(x,d);
 70                 else Rotate(y,d),Rotate(x,d);
 71             }else Rotate(x,son[y][0]==x);
 72         }
 73         pushup(x);
 74         if ( !s ) rt = x;
 75     }
 76     inline int find( int x, int k ){
 77         pushdown(x);
 78         int tot = size[ls]+1;
 79         if ( tot == k ) return x;
 80         return tot>k ? find(ls,k) : find(rs,k-tot);
 81     }
 82     //-----------------------------------
 83     inline void Prev(){pos--;}
 84     inline void Next(){pos++;}
 85     inline void Move( int k ){pos = k+1;}
 86     inline void Get(){
 87         Splay(find(rt,pos+1),0);
 88         putchar( val[rt] );
 89         puts( "" );
 90     }
 91     inline void Rotate( int n ){
 92         int l = find(rt,pos);
 93         int r = find(rt,pos+n+1);
 94         Splay(l,0);Splay(r,l);
 95         rev[key_val] ^= 1;
 96     }
 97     inline void Insert( int n ){
 98         for ( int i = 1; i <= n; i ++ ){
 99             str[i] = getchar();
100             while ( str[i] < 32 || str[i] > 126 )
101                 str[i] = getchar();
102         }
103         int l = find(rt,pos);
104         int r = find(rt,pos+1);
105         Splay(l,0);Splay(r,l);
106         Build(son[r][0],r,1,n);
107         pushup(r);pushup(l);
108     }
109     inline void Delete( int n ){
110         int l = find(rt,pos);
111         int r = find(rt,pos+n+1);
112         Splay(l,0);Splay(r,l);
113         pre[key_val] = key_val = 0;
114         pushup(r);pushup(l);
115     }
116     //----------------------------Debug
117     inline void Travel( int x ){
118         if ( !x ) return;
119         Travel(son[x][0]);
120         printf( "节点%2d :左儿子%2d 右儿子%2d ",x, son[x][0], son[x][1] );
121         printf( "父节点%2d val = %2c size = %2d\n", pre[x], val[x], size[x] );
122         Travel(son[x][1]);
123     }
124     void Debug(){
125         puts( "--------------------" );
126         printf( "%d\n", rt );
127         Travel( rt );
128         puts( "--------------------" );
129     }
130     char str[N];
131     int pos, size[N], rev[N];
132 }sp;
133 int main(){
134     sp.init();    
135     scanf( "%d", &m );
136     for ( int i = 1; i <= m; i ++ )
137     {
138         scanf( "%s", op );
139         if ( op[0] == 'M' || op[0] == 'R' ) scanf( "%d", &k );
140         if ( op[0] == 'I' || op[0] == 'D' ) scanf( "%d", &k );
141         if ( op[0] == 'P' ) sp.Prev();
142         if ( op[0] == 'N' ) sp.Next();
143         if ( op[0] == 'G' ) sp.Get();
144         if ( op[0] == 'M' ) sp.Move(k);
145         if ( op[0] == 'I' ) sp.Insert(k);
146         if ( op[0] == 'R' ) sp.Rotate(k);
147         if ( op[0] == 'D' ) sp.Delete(k);
148     }
149     return 0;
150 }
View Code

 

posted @ 2016-03-02 15:28  羁旅  阅读(114)  评论(0编辑  收藏  举报