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标记,因为删除、插入、翻转等操作都是建立在查找制定位置的节点这一操作上的,所以我们只需要在查找操作中下传标记。(下传标记和标记都要用“反转”方式而不是“设置”方式,因为以前有可能已经有了标志)

 #include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 2100000
using namespace std; struct Splay {
int pre[maxn], son[maxn][], siz[maxn], ntot, root;
char val[maxn];
bool inv[maxn];
int trash[maxn], stot; int newnode( char ch, int p ) {
int nd;
if( stot ) nd = trash[stot--];
else nd = ++ntot;
val[nd] = ch;
pre[nd] = p;
son[nd][] = son[nd][] = ;
siz[nd] = ;
inv[nd] = false;
return nd;
}
Splay():ntot(),stot(){
root = newnode( '^', );
son[root][] = newnode( '$', root );
}
void pushdown( int nd ) {
if( inv[nd] ) {
swap( son[nd][], son[nd][] );
if( son[nd][] ) inv[son[nd][]] ^= true;
if( son[nd][] ) inv[son[nd][]] ^= true;
inv[nd] = false;
}
}
void update( int nd ) {
siz[nd] = siz[son[nd][]]+siz[son[nd][]]+;
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d]; son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][] ] = s;
else root = s; pre[nd] = s;
pre[s] = p;
if( ss ) pre[ss] = nd; update( nd );
update( s );
}
void splay( int nd, int top ) {
while( pre[nd]!=top ) {
int p = pre[nd];
int nl = nd==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( pl==nl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
int find( int pos ) {
int nd = root;
while() {
pushdown( nd );
int ls = siz[son[nd][]];
if( pos<=ls ) {
nd = son[nd][];
} else if( pos>=ls+ ) {
nd = son[nd][];
pos -= ls+;
} else {
break;
}
}
return nd;
}
int build( int lf, int rg, int p, char *str ) { // [lf,rg]
if( lf>rg ) return ;
if( lf==rg ) return newnode( str[lf], p );
int mid = (lf+rg)>>;
int nd = newnode( str[mid], p );
son[nd][] = build( lf, mid-, nd, str );
son[nd][] = build( mid+, rg, nd, str );
update( nd );
return nd;
}
void insert( int pos, int n, char *str ) {
int lnode = find( pos );
int rnode = find( pos+ );
splay( lnode, );
splay( rnode, lnode );
int nd = build( , n-, rnode, str );
son[rnode][] = nd;
splay( nd, );
}
void erase_subtree( int nd ) {
if( !nd ) return;
erase_subtree( son[nd][] );
erase_subtree( son[nd][] );
trash[++stot] = nd;
}
void erase( int lf, int rg ) {
int lnode = find(lf-);
int rnode = find(rg+);
splay( lnode, );
splay( rnode, lnode );
int nd = son[rnode][];
son[rnode][] = ;
erase_subtree( nd );
update( rnode );
splay( rnode, );
}
void reverse( int lf, int rg ) {
int lnode = find( lf- );
int rnode = find( rg+ );
splay( lnode, );
splay( rnode, lnode );
inv[son[rnode][]] ^= true;
}
char get( int pos ) {
int nd = find(pos);
char ch = val[nd];
splay( nd, );
return ch;
}
void print( int nd ) {
if( !nd ) return;
print(son[nd][]);
fprintf( stderr, "%c", val[nd] );
print(son[nd][]);
}
}; Splay T;
int n, cur_pos;
int len;
char str[maxn]; void getstr( int len ) {
while( (str[]=getchar())!='\n' );
for( int i=; i<len; i++ )
str[i] = getchar();
}
int main() {
scanf( "%d", &n );
cur_pos = ;
for( int i=; i<=n; i++ ) {
char ch[];
int k;
scanf( "%s", ch );
//fprintf( stderr, "Process %d: %s\n", i, ch );
switch( ch[] ) {
case 'M':
scanf( "%d", &k );
cur_pos = k+;
break;
case 'I':
scanf( "%d", &len );
getstr(len);
T.insert( cur_pos, len, str );
break;
case 'D':
scanf( "%d", &len );
T.erase( cur_pos+, cur_pos+len );
break;
case 'R':
scanf( "%d", &len );
T.reverse( cur_pos+, cur_pos+len );
break;
case 'G':
printf( "%c\n", T.get(cur_pos+) );
break;
case 'P':
cur_pos--;
break;
case 'N':
cur_pos++;
break;
}
//fprintf( stderr, "Finished, curent state: " );
//T.print(T.root);
//fprintf( stderr, "\n" );
//fprintf( stderr, "cur_pos=%d\n\n", cur_pos );
} }

bzoj 1507

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

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

 #include <cstdio>
#define maxn 2100000 struct Splay {
int pre[maxn], son[maxn][], siz[maxn], ntot, root;
int trash[maxn], stot;
char val[maxn]; int newnode( char ch, int p ) {
int nd;
if( stot ) nd = trash[stot--];
else nd = ++ntot;
val[nd] = ch;
pre[nd] = p;
son[nd][] = son[nd][] = ;
siz[nd] = ;
return nd;
}
Splay() {
root = newnode( '^', );
son[root][] = newnode( '$', root );
update( root );
}
void update( int nd ) {
siz[nd] = siz[son[nd][]]+siz[son[nd][]]+;
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d]; son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][] ] = s;
else root = s; pre[nd] = s;
pre[s] = p;
if( ss ) pre[ss] = nd; update( nd );
update( s );
}
void splay( int nd, int top ) {
while( pre[nd]!=top ) {
int p = pre[nd];
int nl = nd==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
int find( int pos ) {
int nd = root;
while( ) {
int ls = siz[son[nd][]];
if( pos<=ls ) {
nd = son[nd][];
} else if( pos>=ls+ ) {
nd = son[nd][];
pos -= ls+;
} else {
break;
}
}
return nd;
}
int build( int p, int lf, int rg, char *str ) {
if( lf>rg ) return ;
int mid = (lf+rg)>>;
int nd = newnode( str[mid], p );
son[nd][] = build( nd, lf, mid-, str );
son[nd][] = build( nd, mid+, rg, str );
update( nd );
return nd;
}
void insert( int pos, int n, char *str ) {
int lnd = find(pos);
int rnd = find(pos+);
splay(lnd,);
splay(rnd,lnd);
son[rnd][] = build( rnd, , n-, str );
splay( son[rnd][], );
}
void erase_subtree( int nd ) {
if( !nd ) return;
erase_subtree( son[nd][] );
erase_subtree( son[nd][] );
trash[++stot] = nd;
}
void erase( int lf, int rg ) {
int lnd = find(lf-);
int rnd = find(rg+);
splay( lnd, );
splay( rnd, lnd );
erase_subtree( son[rnd][] );
son[rnd][] = ;
update( rnd );
splay( rnd, );
}
char get( int pos ) {
int nd = find(pos);
char ch = val[nd];;
splay( nd, );
return ch;
}
}; int n, cur_pos, len;
Splay T; char *getstr( int len ) {
static char str[maxn];
while( getchar()!='\n' );
for( int i=; i<len; i++ )
while( (str[i] = getchar())=='\n' );
return str;
} int main() {
scanf( "%d", &n );
cur_pos = ;
for( int i=; i<=n; i++ ) {
char ch[];
int k;
scanf( "%s", ch );
// fprintf( stderr, "Process %d: %s\n", i, ch );
switch(ch[]) {
case 'M':
scanf( "%d", &k );
cur_pos = k+;
break;
case 'I':
scanf( "%d", &len );
T.insert( cur_pos, len, getstr(len) );
break;
case 'D':
scanf( "%d", &len );
T.erase( cur_pos+, cur_pos+len );
break;
case 'G':
scanf( "%d", &len );
for( int i=; i<=len; i++ )
putchar( T.get(cur_pos+i) );
printf( "\n" );
break;
case 'P':
cur_pos--;
break;
case 'N':
cur_pos++;
break;
}
}
}

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

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

    Splay Splay序列维护的模板题了……为了便于处理边界情况,我们可以先插入两个空格当作最左端和最右端,然后……其实本题主要考察的就是Build.splay和Findkth这三个操作,我们可以实现 ...

  2. iOS开发那些事-iOS应用本地化-文本信息本地化

    文本信息本地化在本地化工作中占有很大的比例.包括了:应用名称本地化.系统按钮和信息本地化,以及静态文本信息本地化. 系统按钮和信息本地化 还记得天气预报应用背后的“完成”按钮吗,它在中文环境下是“完成 ...

  3. RichTextBox控件-主要用于输入输出编辑文本信息

    1.在RichTextBox控件中添加超链接文字 private void btn_Add_Click(object sender, EventArgs e) { rtbox_HyperLink.Ap ...

  4. 使用freemaker 导出word 含多张图片,若无图片则显示文本信息

    1.使用的Microsoft Office 2007,添加一个无边框的表格,并插入一张图片,最后另存为编码utf-8,一开始保存的word xml格式的,图片的base64编码位于文档最后,暂时没有找 ...

  5. [日常] Go-逐行读取文本信息

    go逐行读取文本信息:1.os包提供了操作系统函数的不依赖平台的接口,Open方法打开一个文件用于读取,func Open(name string) (file *File, err error)2. ...

  6. ArcGIS中删除“点”附带的对应“文本信息”

    现状: 用ArcMap打开对应的.mxd文件,导入KML数据后,几何类型“点” - 每一个点都附带对应的文本信息“Placemark”,如下图: 问题:ArcGIS中如何 删除“点”附带的对应“文本信 ...

  7. Selenium 获取文本信息方法+select(定位)

    1.通过先定位到具体的元素然后通过text方法获取文本信息,如获取控件名称等 driver.find_element_by_xpath("//div[/h1").text 2.直接 ...

  8. 使用jQuery匹配文档中所有的li元素,返回一个jQuery对象,然后通过数组下标的方式读取jQuery集合中第1个DOM元素,此时返回的是DOM对象,然后调用DOM属性innerHTML,读取该元素 包含的文本信息

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 用FireDAC获取 SQL SERVER错误文本信息

    SQL SERVER获取错误文本信息,BDE.adoquery一直取不到,FDQuery可以了 Some DBMS, like SQL Server, return messages as an ad ...

随机推荐

  1. NYOJ 228 士兵杀敌(五) (模拟)

    {题目链接](http://acm.nyist.net/JudgeOnline/problem.php?pid=228) 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为0~M,每次有任务的时候 ...

  2. NYOJ 1063 生活的烦恼 (二叉树)

    题目链接 描述 生活的暑假刚集训开始,他要决心学好字典树,二叉树,线段树和各种树,但生活在OJ上刷题的时候就遇到了一个特别烦恼的问题.那当然就是他最喜欢的二二叉树咯!题目是这样的:给你一颗非空的二叉树 ...

  3. LeetCode之数据流中第一个唯一的数字

    使用一个Map维护数字出现的次数,使用一个链表维护只出现一次的数,使用一个变量记录是否找到过终止数字. AC代码: public class Solution { /* * @param : a co ...

  4. 爬虫--Scrapy之Downloader Middleware

    下载器中间件(Downloader Middleware) 下载器中间件是介于Scrapy的request/response处理的钩子框架. 是用于全局修改Scrapy request和respons ...

  5. Traffic-Server配置(待补充和更新)

    Server 5.3.2 测试1.裸盘:remap.configmap http://192.168.227.131 http://192.168.227.131:8080 #traffic_serv ...

  6. password passphrase passcode 的区别

    In general, passphrases are long passwords and passcodes are numeric-only passwords.

  7. 64_p8

    python2-cotyledon-tests-1.6.7-2.fc26.noarch.rpm 12-Feb-2017 10:28 23182 python2-couchdb-1.0-6.fc26.n ...

  8. ubuntu遇到的 the system is runing low-graphics mode 问题

    不知道修改了什么,然后开机显示the system is runing low-graphics mode 看过博客使用如下方法成功进入系统,但是显示分辨率很低,显示 built-in display ...

  9. Tutorial 6: ViewSets & Routers

    转载自:http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/ Tutorial 6: ViewSets & ...

  10. 运行级别(run level)

    inittab是很多linux版本的启动脚本.Linux在完成核内引导以后,就开始运行init程序,它的进程号是1,是所有其他进程的起点.init需要读取/etc/inittab,该文件告诉init在 ...