bzoj 1269 bzoj 1507 Splay处理文本信息

bzoj 1269

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

大致思路:

用splay维护整个文本信息,splay树的中序遍历即为该文本。

收获:

1、可以先在文本开始和结尾个插入一个节点,然后每次操作都适当调整位置,这样可以减少特判(插入一段文本到0位置,在最后插入一段文本。。。)

2、查找一段文本[lf,rg],可以先找到位置为lf-1的节点(因为1,不用特判没有了),splay到根,再找到rg+1的节点,旋转到根的下面,这样根右子节点的左子树就是我们要找的内容。

3、翻转一段文本,有点像线段树,给节点打上lazy标记,因为删除、插入、翻转等操作都是建立在查找制定位置的节点这一操作上的,所以我们只需要在查找操作中下传标记。(下传标记和标记都要用“反转”方式而不是“设置”方式,因为以前有可能已经有了标志)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #define maxn 2100000
  5 using namespace std;
  6 
  7 struct Splay {
  8     int pre[maxn], son[maxn][2], siz[maxn], ntot, root;
  9     char val[maxn];
 10     bool inv[maxn];
 11     int trash[maxn], stot;
 12 
 13     int newnode( char ch, int p ) {
 14         int nd;
 15         if( stot ) nd = trash[stot--];
 16         else nd = ++ntot;
 17         val[nd] = ch;
 18         pre[nd] = p;
 19         son[nd][0] = son[nd][1] = 0;
 20         siz[nd] = 1;
 21         inv[nd] = false;
 22         return nd;
 23     }
 24     Splay():ntot(0),stot(0){
 25         root = newnode( '^', 0 );
 26         son[root][1] = newnode( '$', root );
 27     }
 28     void pushdown( int nd ) {
 29         if( inv[nd] ) {
 30             swap( son[nd][0], son[nd][1] );
 31             if( son[nd][0] ) inv[son[nd][0]] ^= true;
 32             if( son[nd][1] ) inv[son[nd][1]] ^= true;
 33             inv[nd] = false;
 34         }
 35     }
 36     void update( int nd ) {
 37         siz[nd] = siz[son[nd][0]]+siz[son[nd][1]]+1;
 38     }
 39     void rotate( int nd, int d ) {
 40         int p = pre[nd];
 41         int s = son[nd][!d];
 42         int ss = son[s][d];
 43         
 44         son[nd][!d] = ss;
 45         son[s][d] = nd;
 46         if( p ) son[p][ nd==son[p][1] ] = s;
 47         else root = s;
 48 
 49         pre[nd] = s;
 50         pre[s] = p;
 51         if( ss ) pre[ss] = nd;
 52 
 53         update( nd );
 54         update( s );
 55     }
 56     void splay( int nd, int top ) {
 57         while( pre[nd]!=top ) {
 58             int p = pre[nd];
 59             int nl = nd==son[p][0];
 60             if( pre[p]==top ) {
 61                 rotate( p, nl );
 62             } else {
 63                 int pp = pre[p];
 64                 int pl = p==son[pp][0];
 65                 if( pl==nl ) {
 66                     rotate( pp, pl );
 67                     rotate( p, nl );
 68                 } else {
 69                     rotate( p, nl );
 70                     rotate( pp, pl );
 71                 }
 72             }
 73         }
 74     }
 75     int find( int pos ) {
 76         int nd = root;
 77         while(1) {
 78             pushdown( nd );
 79             int ls = siz[son[nd][0]];
 80             if( pos<=ls ) {
 81                 nd = son[nd][0];
 82             } else if( pos>=ls+2 ) {
 83                 nd = son[nd][1];
 84                 pos -= ls+1;
 85             } else {
 86                 break;
 87             }
 88         }
 89         return nd;
 90     }
 91     int build( int lf, int rg, int p, char *str ) {    //    [lf,rg]
 92         if( lf>rg ) return 0;
 93         if( lf==rg ) return newnode( str[lf], p );
 94         int mid = (lf+rg)>>1;
 95         int nd = newnode( str[mid], p );
 96         son[nd][0] = build( lf, mid-1, nd, str );
 97         son[nd][1] = build( mid+1, rg, nd, str );
 98         update( nd );
 99         return nd;
100     }
101     void insert( int pos, int n, char *str ) {
102         int lnode = find( pos );
103         int rnode = find( pos+1 );
104         splay( lnode, 0 );
105         splay( rnode, lnode );
106         int nd = build( 0, n-1, rnode, str );
107         son[rnode][0] = nd;
108         splay( nd, 0 );
109     }
110     void erase_subtree( int nd ) {
111         if( !nd ) return;
112         erase_subtree( son[nd][0] );
113         erase_subtree( son[nd][1] );
114         trash[++stot] = nd;
115     }
116     void erase( int lf, int rg ) {
117         int lnode = find(lf-1);
118         int rnode = find(rg+1);
119         splay( lnode, 0 );
120         splay( rnode, lnode );
121         int nd = son[rnode][0];
122         son[rnode][0] = 0;
123         erase_subtree( nd );
124         update( rnode );
125         splay( rnode, 0 );
126     }
127     void reverse( int lf, int rg ) {
128         int lnode = find( lf-1 );
129         int rnode = find( rg+1 );
130         splay( lnode, 0 );
131         splay( rnode, lnode );
132         inv[son[rnode][0]] ^= true;
133     }
134     char get( int pos ) {
135         int nd = find(pos);
136         char ch = val[nd];
137         splay( nd, 0 );
138         return ch;
139     }
140     void print( int nd ) {
141         if( !nd ) return;
142         print(son[nd][0]);
143         fprintf( stderr, "%c", val[nd] );
144         print(son[nd][1]);
145     }
146 };
147 
148 Splay T;
149 int n, cur_pos;
150 int len;
151 char str[maxn];
152 
153 void getstr( int len ) {
154     while( (str[0]=getchar())!='
' );
155     for( int i=0; i<len; i++ )
156         str[i] = getchar();
157 }
158 int main() {
159     scanf( "%d", &n );
160     cur_pos = 1;
161     for( int i=1; i<=n; i++ ) {
162         char ch[100];
163         int k;
164         scanf( "%s", ch );
165         //fprintf( stderr, "Process %d: %s
", i, ch );
166         switch( ch[0] ) {
167             case 'M':
168                 scanf( "%d", &k );
169                 cur_pos = k+1;
170                 break;
171             case 'I':
172                 scanf( "%d", &len );
173                 getstr(len);
174                 T.insert( cur_pos, len, str );
175                 break;
176             case 'D':
177                 scanf( "%d", &len );
178                 T.erase( cur_pos+1, cur_pos+len );
179                 break;
180             case 'R':
181                 scanf( "%d", &len );
182                 T.reverse( cur_pos+1, cur_pos+len );
183                 break;
184             case 'G':
185                 printf( "%c
", T.get(cur_pos+1) );
186                 break;
187             case 'P':
188                 cur_pos--;
189                 break;
190             case 'N':
191                 cur_pos++;
192                 break;
193         }
194         //fprintf( stderr, "Finished, curent state: " );
195         //T.print(T.root);
196         //fprintf( stderr, "
" );
197         //fprintf( stderr, "cur_pos=%d

", cur_pos );
198     }
199 
200 }
View Code

bzoj 1507

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1507

和上一道题差不多(还简单一点,不用反转),但输出要求是一段,splay可以每次调用读取一个字符(因为有splay操作,所以挨在一起的点每次就在根的右边)

  1 #include <cstdio>
  2 #define maxn 2100000
  3 
  4 struct Splay {
  5     int pre[maxn], son[maxn][2], siz[maxn], ntot, root;
  6     int trash[maxn], stot;
  7     char val[maxn];
  8 
  9     int newnode( char ch, int p ) {
 10         int nd;
 11         if( stot ) nd = trash[stot--];
 12         else nd = ++ntot;
 13         val[nd] = ch;
 14         pre[nd] = p;
 15         son[nd][0] = son[nd][1] = 0;
 16         siz[nd] = 1;
 17         return nd;
 18     }
 19     Splay() {
 20         root = newnode( '^', 0 );
 21         son[root][1] = newnode( '$', root );
 22         update( root );
 23     }
 24     void update( int nd ) {
 25         siz[nd] = siz[son[nd][0]]+siz[son[nd][1]]+1;
 26     }
 27     void rotate( int nd, int d ) {
 28         int p = pre[nd];
 29         int s = son[nd][!d];
 30         int ss = son[s][d];
 31 
 32         son[nd][!d] = ss;
 33         son[s][d] = nd;
 34         if( p ) son[p][ nd==son[p][1] ] = s;
 35         else root = s;
 36 
 37         pre[nd] = s;
 38         pre[s] = p;
 39         if( ss ) pre[ss] = nd;
 40 
 41         update( nd );
 42         update( s );
 43     }
 44     void splay( int nd, int top ) {
 45         while( pre[nd]!=top ) {
 46             int p = pre[nd];
 47             int nl = nd==son[p][0];
 48             if( pre[p]==top ) {
 49                 rotate( p, nl );
 50             } else {
 51                 int pp = pre[p];
 52                 int pl = p==son[pp][0];
 53                 if( nl==pl ) {
 54                     rotate( pp, pl );
 55                     rotate( p, nl );
 56                 } else {
 57                     rotate( p, nl );
 58                     rotate( pp, pl );
 59                 }
 60             }
 61         }
 62     }
 63     int find( int pos ) {
 64         int nd = root;
 65         while( 1 ) {
 66             int ls = siz[son[nd][0]];
 67             if( pos<=ls ) {
 68                 nd = son[nd][0];
 69             } else if( pos>=ls+2 ) {
 70                 nd = son[nd][1];
 71                 pos -= ls+1;
 72             } else {
 73                 break;
 74             }
 75         }
 76         return nd;
 77     }
 78     int build( int p, int lf, int rg, char *str ) {
 79         if( lf>rg ) return 0;
 80         int mid = (lf+rg)>>1;
 81         int nd = newnode( str[mid], p );
 82         son[nd][0] = build( nd, lf, mid-1, str );
 83         son[nd][1] = build( nd, mid+1, rg, str );
 84         update( nd );
 85         return nd;
 86     }
 87     void insert( int pos, int n, char *str ) {
 88         int lnd = find(pos);
 89         int rnd = find(pos+1);
 90         splay(lnd,0);
 91         splay(rnd,lnd);
 92         son[rnd][0] = build( rnd, 0, n-1, str );
 93         splay( son[rnd][0], 0 );
 94     }
 95     void erase_subtree( int nd ) {
 96         if( !nd ) return;
 97         erase_subtree( son[nd][0] );
 98         erase_subtree( son[nd][1] );
 99         trash[++stot] = nd;
100     }
101     void erase( int lf, int rg ) {
102         int lnd = find(lf-1);
103         int rnd = find(rg+1);
104         splay( lnd, 0 );
105         splay( rnd, lnd );
106         erase_subtree( son[rnd][0] );
107         son[rnd][0] = 0;
108         update( rnd );
109         splay( rnd, 0 );
110     }
111     char get( int pos ) {    
112         int nd = find(pos);
113         char ch = val[nd];;
114         splay( nd, 0 );
115         return ch;
116     }
117 };
118 
119 int n, cur_pos, len;
120 Splay T;
121 
122 char *getstr( int len ) {
123     static char str[maxn];
124     while( getchar()!='
' );
125     for( int i=0; i<len; i++ )
126         while( (str[i] = getchar())=='
' );
127     return str;
128 }
129 
130 int main() {
131     scanf( "%d", &n );
132     cur_pos = 1;
133     for( int i=1; i<=n; i++ ) { 
134         char ch[32];
135         int k;
136         scanf( "%s", ch );
137     //    fprintf( stderr, "Process %d: %s
", i, ch );
138         switch(ch[0]) {
139             case 'M':
140                 scanf( "%d", &k );
141                 cur_pos = k+1;
142                 break;
143             case 'I':
144                 scanf( "%d", &len );
145                 T.insert( cur_pos, len, getstr(len) );
146                 break;
147             case 'D':
148                 scanf( "%d", &len );
149                 T.erase( cur_pos+1, cur_pos+len );
150                 break;
151             case 'G':
152                 scanf( "%d", &len );
153                 for( int i=1; i<=len; i++ )
154                     putchar( T.get(cur_pos+i) );
155                 printf( "
" );
156                 break;
157             case 'P':
158                 cur_pos--;
159                 break;
160             case 'N':
161                 cur_pos++;
162                 break;
163         }
164     }
165 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4277711.html