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. python笔记之BytesIO

    1. 什么是BytesIO BytesIO与StringIO类似,不同的是StringIO只能存放string,BytesIO是用来存放bytes的,它提供了在内存中读写字节的能力. 即在内存中读写字 ...

  2. 去掉input获取focus时的边框

    贴图,问题如下: 尽管已经设置输入框的border为none,当输入框focus时扔会出现浏览器自带的边框 解决方法,添加如下样式即可,.fs_input为输入框样式 ---------------- ...

  3. leetcode.C.4. Median of Two Sorted Arrays

    4. Median of Two Sorted Arrays 这应该是最简单最慢的方法了,因为本身为有序,所以比较后排序再得到中位数. double findMedianSortedArrays(in ...

  4. 浅谈iOS多线程

    浅谈iOS多线程 首先,先看看进程和线程的概念. 图1.1 这一块不难理解,重点点下他们的几个重要区别: 1,地址空间和资源:进程可以申请和拥有系统资源,线程不行.资源进程间相互独立,同一进程的各线程 ...

  5. Java线上应用故障之CPU占用高排查与定位

    最近线上频繁报警CPU空闲不足,故紧急排查后分享给大家 1.使用top命令,获取占用CPU最高的进程号 2.查看线程号对应的进程信息 命令:ps -ef|grep 22630 3.查看进程对应的线程信 ...

  6. 343.Integer Break---dp

    题目链接:https://leetcode.com/problems/integer-break/description/ 题目大意:给定一个自然数,将其分解,对其分解的数作乘积,找出最大的乘积结果. ...

  7. [SVN技巧]代码提交中遇到的两个问题及其解决方案

    前言 SVN在使用的过程中会遇到各种各样的问题,小黑在最近的使用中,遇到如下的两个问题,这里贴出来供大家参考 问题记录 SVN在源码仓库中不存在,导致无法删除和上传 问题提示: Working cop ...

  8. Tutorial 1: Serialization

    转载自:http://www.django-rest-framework.org/tutorial/1-serialization/#tutorial-1-serialization Tutorial ...

  9. PHP利用rand(1,100)函数产生10个1~100之间的随机数

    //echo rand(1,100); $max=0; $min=100; for($i=0;$i<=9;$i++){ $rand[$i]=rand(1,100); if($rand[$i]&g ...

  10. linux中getmntent setmntent endmntent 用法例子

    mntent 结构是在 <mntent.h> 中定义,如下:               struct mntent {                      char    *mnt ...