题目分析:题目不难,注意细节就好,涉及到splay的区间剪切以及区间翻转操作。
代码如下:
/*
本算法需要两个虚拟节点:0、n+1
clear () 初始化
newNode ( int v , SplayNode* f ) 新建节点并赋值v以及令其父亲为f
init ( int n ) 初始化
rotate ( SplayNode* o , int d ) 旋转,d=0表示左旋,d=1表示右旋
splay ( SplayNode* o , SplayNode* f ) 伸展o直到o的父节点为f为止
select ( int k , SplayNode* f ) 选择第k个元素并将其旋转到其父节点为f为止(不计虚拟节点)
SplayNode* get ( int l , int r ) 返回区间[l,r]:即将l-1旋转到根,将r+1旋转为l-1的右节点
void split ( int l , int r , SplayNode* &o ) 将区间[l,r]剪切到o
void merge ( int pos , SplayNode* o ) 将o插入到pos以及pos+1之间:即将pos旋转到根,pos+1旋转为pos的右节点
void cut ( int l , int r , int pos ) 将区间[l,r]剪切出来并插入到pos的右端
void reverse ( int l , int r ) 翻转区间[l,r]
void print ( SplayNode* o , int &cnt , int n ) 中序输出整个区间
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
const int MAXN = 300005 ;
struct SplayNode {
SplayNode *c[2] , *f ;
int s , v , rev ;
SplayNode () : s ( 0 ) {}
void pushup () {
s = c[0] -> s + c[1] -> s + 1 ;
}
void pushdown () {
if ( rev ) {
rev = 0 ;
swap ( c[0] , c[1] ) ;
c[0] -> rev ^= 1 ;
c[1] -> rev ^= 1 ;
}
}
} Tnull , *null = &Tnull ;
struct Splay {
SplayNode node[MAXN] , *cur , *root ;
Splay () : cur ( node ) , root ( null ) {}
void clear () {
root = null ;
cur = node ;
}
SplayNode* newNode ( int v , SplayNode* f ) {
cur -> v = v ;
cur -> s = 1 ;
cur -> rev = 0 ;
cur -> c[0] = cur -> c[1] = null ;
cur -> f = f ;
return cur ++ ;
}
void init ( int n ) {
clear () ;
FOR ( i , 0 , n + 1 ) {
SplayNode* o = newNode ( i , null ) ;
o -> c[0] = root ;
root -> f = o ;
root = o ;
root -> pushup () ;
}
}
//旋转
void rotate ( SplayNode* o , int d ) {
SplayNode* p = o -> f ;
p -> pushdown () ;//先pushdown父节点
o -> pushdown () ;//后pushdown自身
p -> c[!d] = o -> c[d] ;
o -> c[d] -> f = p ;
o -> f = p -> f ;
if ( p -> f != null ) {
if ( p == p -> f -> c[0] ) p -> f -> c[0] = o ;
else p -> f -> c[1] = o ;
}
o -> c[d] = p ;
p -> f = o ;
p -> pushup () ;
if ( root == p ) root = o ;
}
//伸展o直到o的父节点为f为止
void splay ( SplayNode* o , SplayNode* f ) {
while ( o -> f != f ) {
SplayNode* p = o -> f ;
if ( p -> f == f ) {
if ( o == p -> c[0] ) rotate ( o , 1 ) ;
else rotate ( o , 0 ) ;
} else {
if ( p == p -> f -> c[0] ) {
if ( o == p -> c[0] ) rotate ( p , 1 ) , rotate ( o , 1 ) ;
else rotate ( o , 0 ) , rotate ( o , 1 ) ;
} else {
if ( o == p -> c[1] ) rotate ( p , 0 ) , rotate ( o , 0 ) ;
else rotate ( o , 1 ) , rotate ( o , 0 ) ;
}
}
}
o -> pushup () ;
}
//选择第k个元素并将其旋转到其父节点为f为止(不计虚拟节点)
void select ( int k , SplayNode* f ) {
SplayNode* o = root ;
++ k ; //空出虚拟节点的位置
while ( o != null ) {
o -> pushdown () ; //先pushdown
int s = o -> c[0] -> s ;//后计算节点数
if ( k == s + 1 ) break ;
if ( k <= s ) o = o -> c[0] ;
else {
k -= s + 1 ;
o = o -> c[1] ;
}
}
splay ( o , f ) ;
}
//返回区间[l,r]
SplayNode* get ( int l , int r ) {
select ( l - 1 , null ) ;
select ( r + 1 , root ) ;
return root -> c[1] -> c[0] ;
}
//翻转区间[l,r]
void reverse ( int l , int r ) {
SplayNode* o = get ( l , r ) ;
o -> rev ^= 1 ;
}
//将区间[l,r]剪切到o
void split ( int l , int r , SplayNode* &o ) {
o = get ( l , r ) ;
o -> f = null ;
root -> c[1] -> c[0] = null ;
root -> c[1] -> pushup () ;
root -> pushup () ;
}
//将o插入到pos以及pos+1之间
void merge ( int pos , SplayNode* o ) {
get ( pos + 1 , pos ) ;
o -> f = root -> c[1] ;
root -> c[1] -> c[0] = o ;
root -> c[1] ->pushup () ;
root -> pushup () ;
}
//将区间[l,r]剪切出来并插入到pos的右端
void cut ( int l , int r , int pos ) {
SplayNode* o ;
split ( l , r , o ) ;
merge ( pos , o ) ;
}
//中序输出整个区间
void print ( SplayNode* o , int &cnt , int n ) {
o -> pushdown () ;
if ( o -> c[0] != null ) print ( o -> c[0] , cnt , n ) ;
if ( o -> v && o -> v != n + 1 ) printf ( "%d%c" , o -> v , ++ cnt < n ? ' ' : '\n' ) ;
if ( o -> c[1] != null ) print ( o -> c[1] , cnt , n ) ;
}
} T ;
int n , m ;
void solve () {
int l , r , pos ;
char s[5] ;
T.init ( n ) ;
while ( m -- ) {
scanf ( "%s%d%d" , s , &l , &r ) ;
if ( s[0] == 'C' ) {
scanf ( "%d" , &pos ) ;
T.cut ( l , r , pos ) ;
} else T.reverse ( l , r ) ;
}
int cnt = 0 ;
T.print ( T.root , cnt , n ) ;
}
int main () {
while ( ~scanf ( "%d%d" , &n , &m ) && ( n >= 0 || m >= 0 ) )
solve () ;
return 0 ;
}