bzoj 1269 Splay处理文本信息

题目: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())!=‘\n‘ );
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\n", 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\n", 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, "\n" );
197         //fprintf( stderr, "cur_pos=%d\n\n", cur_pos );
198     }
199
200 }

时间: 2024-10-27 05:38:12

bzoj 1269 Splay处理文本信息的相关文章

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

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] /* [move k] 指令.直接 把pos改成k.表示改变光标位置 [insert n s],在pos后面插入一个长度为n的字符串. 这个操作. 我们可以先找出第pos个节点x和第pos+1个节点y (这里其实就是找第pos小的数,在splay上,加一个size大小域,找第k小即可.) (伸展树在旋转的过程中,不会影响性质,即,它中序遍历的结果始终是字符串s1..n) 我们执行splay x 0 再执行splay y x 然后

Jquery获取select选中的option的文本信息

注意:下面用的$(this)代表当前选中的select框 第一种: $(this).children("option:selected").text(); 第二种: $(this).children("option:selected").html(); Jquery获取select选中的option的文本信息,布布扣,bubuko.com

用扑克牌保存文本信息

事实上,本文是在Peter Jerde的How much information can be stored by ordering 52 playing cards文章基础上翻译.改编和扩展而来的.当然这是经过Jerde本人首肯的. 注意本文方法并非最优,也没有完全利用所有的信息空间,只是简单的尝试. 有数字的地方就有信息.所以扑克牌中保存信息不是什么新鲜事. PDF文档点这里:下载 原文(英文)点这里:访问 这里有两个DEMO. 编码DEMO,解码DEMO 首先是"DEEP IN SHALL

Android:TextView显示富文本信息

最近需要在TextView中显示一些超链接等信息,如URL(点击后跳转),显示网络图片等. 整理如下: 1.显示URl,在需要显示URL超链接的TextView中设置 textview.setText(Html.fromHtml(urlString)) (urlString 用html语法来标识) versionText.setMovementMethod(LinkMovementMethod.getInstance()); 上面一句必须设置,否则将无法跳转. 2.显示网络图片 textview

用扑克牌的排列保存文本信息

有数字的地方就有信息.所以扑克牌中保存信息不是什么新鲜事.根据Peter Jerde的文章改编. 这里有两个DEMO. 编码DEMO,解码DEMO首先是"DEEP IN SHALLOW OUT"(深入浅出)这句话.用扑克牌表示是这样的: 用数字表示"DEEP IN SHALLOW OUT",就是"468397942256655904392271504",然后用短除法计算扑克的位置,最后进行排列.这一过程,叫做编码.解码是逆过程,通过扑克排列,计算

IOS开发之国际化篇第二章:文本信息国际化

本文是以XCode7.2.1为开发平台 在第一章中,我们基本了解了国际化是怎么一会事,介绍到有3种国际化,接下来的几章就会分别介绍这3种国际化,第一个是文本信息国际化 文本信息国际化包含一下几点 系统按钮和信息国际化 应用名称国际化 程序代码中输出的静态文本国际化 -系统按钮和信息国际化 系统本身会自带一些系统的信息,系统按钮等,这一些系统自带的信息提示,按钮文本都是由Cocoa本身自带的,他们都是统一又系统管理,例如Done在英文环境中是Done,还有系统提示信息,如下图,在不同语言环境系统会

【安全牛学习笔记】基本工具-NETCAT(telnet/banner、传输文本信息)

常用工具 经常使用且功能强大 安全从业者必不可少的帮手 Nc / ncat Wireshack Tcpdump NETCAT-----NC 网络工具中的瑞士军刀--小身材.大智慧 侦听模式/传输模式 telnet/获取banner信息 传输文本信息 传输文件目录 加密传输文件 远程控制/木马 加密所有流量 流媒体服务器 远程克隆硬盘 NC-----TELNET/banner nc -nv 1.1.1.1 10 nc -nv 1.1.1.1 25 nc -nv 1.1.1.1 80 root:~#

html抽取文本信息-java版(适合lucene建立索引)

import org.htmlparser.NodeFilter; import org.htmlparser.Parser; import org.htmlparser.beans.StringBean; import org.htmlparser.filters.CssSelectorNodeFilter; import org.htmlparser.util.NodeList; public class HtmlUtil { public static String getText(Str

Windows Phone 带文本信息的进度条

2. [图片Windows Phone 带文本信息的进度条 详细说明:http://wp.662p.com/thread-7980-1-1.html