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标记,因为删除、插入、翻转等操作都是建立在查找制定位置的节点这一操作上的,所以我们只需要在查找操作中下传标记。(下传标记和标记都要用“反转”方式而不是“设置”方式,因为以前有可能已经有了标志)
#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处理文本信息的更多相关文章
- 【BZOJ】【1269】【AHOI2006】文本编辑器editor
Splay Splay序列维护的模板题了……为了便于处理边界情况,我们可以先插入两个空格当作最左端和最右端,然后……其实本题主要考察的就是Build.splay和Findkth这三个操作,我们可以实现 ...
- iOS开发那些事-iOS应用本地化-文本信息本地化
文本信息本地化在本地化工作中占有很大的比例.包括了:应用名称本地化.系统按钮和信息本地化,以及静态文本信息本地化. 系统按钮和信息本地化 还记得天气预报应用背后的“完成”按钮吗,它在中文环境下是“完成 ...
- RichTextBox控件-主要用于输入输出编辑文本信息
1.在RichTextBox控件中添加超链接文字 private void btn_Add_Click(object sender, EventArgs e) { rtbox_HyperLink.Ap ...
- 使用freemaker 导出word 含多张图片,若无图片则显示文本信息
1.使用的Microsoft Office 2007,添加一个无边框的表格,并插入一张图片,最后另存为编码utf-8,一开始保存的word xml格式的,图片的base64编码位于文档最后,暂时没有找 ...
- [日常] Go-逐行读取文本信息
go逐行读取文本信息:1.os包提供了操作系统函数的不依赖平台的接口,Open方法打开一个文件用于读取,func Open(name string) (file *File, err error)2. ...
- ArcGIS中删除“点”附带的对应“文本信息”
现状: 用ArcMap打开对应的.mxd文件,导入KML数据后,几何类型“点” - 每一个点都附带对应的文本信息“Placemark”,如下图: 问题:ArcGIS中如何 删除“点”附带的对应“文本信 ...
- Selenium 获取文本信息方法+select(定位)
1.通过先定位到具体的元素然后通过text方法获取文本信息,如获取控件名称等 driver.find_element_by_xpath("//div[/h1").text 2.直接 ...
- 使用jQuery匹配文档中所有的li元素,返回一个jQuery对象,然后通过数组下标的方式读取jQuery集合中第1个DOM元素,此时返回的是DOM对象,然后调用DOM属性innerHTML,读取该元素 包含的文本信息
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 用FireDAC获取 SQL SERVER错误文本信息
SQL SERVER获取错误文本信息,BDE.adoquery一直取不到,FDQuery可以了 Some DBMS, like SQL Server, return messages as an ad ...
随机推荐
- Codeforces 665E. Beautiful Subarrays (字典树)
题目链接:http://codeforces.com/problemset/problem/665/E (http://www.fjutacm.com/Problem.jsp?pid=2255) 题意 ...
- arch点击硬盘无法挂载
出现问题如下 在使用xfce4桌面的时候在点击硬盘图标时可以挂载虽然要求你输入root密码 但是在使用openbox的时候点击硬盘图标却出现如下提示,权限的问题 Not authorized to p ...
- [006] largest_common_substring
[Description] Given two different strings, find the largest successive common substring. e.g. str1[] ...
- Git远程操作详解【转】
转自:http://www.ruanyifeng.com/blog/2014/06/git_remote.html 作者: 阮一峰 日期: 2014年6月12日 Git是目前最流行的版本管理系统,学会 ...
- C++中string.find()函数,string.find_first_of函数与string::npos
查找字符串a是否包含子串b,不是用strA.find(strB) > 0而是strA.find(strB) != string:nposstring::size_type pos = strA. ...
- Android快速入门(转自 农民伯伯: http://www.cnblogs.com/over140/)
前言 这是前段时间用于公司Android入门培训的资料,学习Android三周时间收集整理的,时间仓促,希望能对像我这样还没入门就直接上项目的人一点帮助 :) 声明 欢迎转载,但请保留文章原始出处: ...
- 64_r3
rubygem-resque-cleaner-0.3.0-5.fc24.noarch.rpm 24-Sep-2016 22:26 22422 rubygem-resque-cleaner-doc-0. ...
- MGR Switch Muti-Primary to single_primary
MGR Muti-Primary 切换 single_primary 模式 原因:因为希望做ProxySQL+MGR之间Proxy层的消耗测试,需要把原有的MGR多主改为单主模式. 修改MGRgrou ...
- JSOI 2017 退役记
意料之中,真的要退役了. 懒得写游记了. Round 2 的时候状态一直不太清醒,最后混了个rank19,准备AFO吧.
- 安装 Xamarin for Visual Studio
总得来说,Xamarin 有“联网自动安装”和“手动安装”两种方式. 说明:本文涉及得资源链接都是官网的,同时,在 我的网盘 也有相关备份. 现在,我就以 Windows 为例来大概说明……(-=-我 ...