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. C - K-inversions URAL - 1523 (dp + 线段树)

    题目链接:https://cn.vjudge.net/contest/275079#problem/C 具体思路:我们可以分层的去建立,假设我们要找k层,我们可以先把满足1.2....k-1层的满足情 ...

  2. tf.segment_sum和tf.unsorted_segment_sum理解实例

    本文来自 guotong1988 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/guotong1988/article/details/77622790 import ...

  3. 前端bootstrap框架禁用响应式的方法

    在Bootstrap中极其重要的一个技术内容便是响应式布局了,一次编码针对不同设备终端的强大能力使得响应式技术愈发流行. 不过正所谓“萝卜青菜各有所爱”,如果你想要使用Bootstrap开发自己的项目 ...

  4. 71.Adam Taylor玩转MicroZed系列第82部分:简单通信接口第2部分

    By Adam Taylor 从上周的博客开始,我们已经进入到Zedboard(而不是MicroZed)板上的OLED显示模块的编程了.然而在正式进入具体的OLED编程之前,我认为有必要验证我们是否已 ...

  5. easyui datagrid 去掉 全选checkbox

    在加载 表格的时候添加事件:onLoadSuccess 在事件中写入下面句,用空代替原有HTML 达到取消效果. $(".datagrid-header-check").html( ...

  6. caffe Python API 之Solver定义

    from caffe.proto import caffe_pb2 s = caffe_pb2.SolverParameter() path='/home/xxx/data/' solver_file ...

  7. GPS位置模拟-安卓

    测试定位功能时都需要位置模拟,一般有如下3种方式: a)手机上安装第三方模拟软件:需要Root: b)PC模拟其中运行app并模拟位置:不能在真机上运行,手机兼容性不能测试到: b)在app中让开发增 ...

  8. Python股票信息抓取(二)

    在一的基础上,想着把所有的折线图放在一个图中,然后图的结果如图所示: 不是略丑,是很丑~ 依然的单进程,只是将图标结果放在了一张图里 代码如下: #-*-coding:utf-8 -*- import ...

  9. Java的Stack类实现List接口真的是个笑话吗

        今天在网上闲逛时看到了这样一个言论,说“Java的Stack类实现List接口的设计是个笑话”.   当然作者这篇文章的重点不是这个,原本我也只是一笑置之,然而看评论里居然还有人附和,说“Ja ...

  10. Android项目包命名规则是怎样的?

    com.example.app.activity | Activity 类com.example.app.widget | 自定义的小UIcom.example.app.db | 数据库相关操作com ...