BZOJ 1500: [NOI2005]维修数列( splay )

splay..... 

------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
 
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
#define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
 
using namespace std;
 
const int maxn = 500000;
const int maxnode = 550000;
const int inf = int( 1e7 );
 
struct Node* null;
queue< Node* > Q;
int seq[ maxn ] , tot , pos;
 
struct Node {
Node *ch[ 2 ] , *p;
int s , v , sum , mx , l_m , r_m;
bool rev , tag;
Node( int _v = 0 ) {
l_m = r_m = sum = mx = v = _v;
ch[ 0 ] = ch[ 1 ] = p = null;
rev = tag = false;
}
inline void relax() {
if( rev ) {
rev = false;
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Rev();
}
if( tag ) {
tag = false;
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Set( v );
}
}
inline void Rev() {
rev ^= 1;
swap( ch[ 0 ] , ch[ 1 ] );
swap( l_m , r_m );
}
inline void Set( int _v ) {
tag = true;
v = _v;
sum = s * _v;
mx = r_m = l_m = _v * ( _v > 0 ? s : 1 );
}
inline void upd() {
s = ch[ 0 ] -> s + ch[ 1 ] -> s + 1;
sum = ch[ 0 ] -> sum + ch[ 1 ] -> sum + v;
l_m = max( ch[ 0 ] -> l_m , ch[ 0 ] -> sum + v + max( 0 , ch[ 1 ] -> l_m ) );
r_m = max( ch[ 1 ] -> r_m , ch[ 1 ] -> sum + v + max( 0 , ch[ 0 ] -> r_m ) );
mx = max( 0 , ch[ 0 ] -> r_m ) + v + max( 0 , ch[ 1 ] -> l_m );
mx = max( mx , max( ch[ 0 ] -> mx , ch[ 1 ] -> mx ) );
}
inline void setc( Node* c , int d ) {
ch[ d ] = c;
c -> p = this;
}
inline bool d() {
return this == p -> ch[ 1 ];
}
void* operator new( size_t ) {
Node* t = Q.front();
Q.pop();
return t;
}
};
 
Node memory[ maxnode ];
Node* root;
 
void rot( Node* t ) {
Node* p = t -> p;
p -> relax();
t -> relax();
int d = t -> d();
p -> p -> setc( t , p -> d() );
p -> setc( t -> ch[ ! d ] , d );
t -> setc( p , ! d );
p -> upd();
if( p == root ) root = t;
}
 
void splay( Node* t , Node* f = null ) {
for( Node* p = t -> p ; p != f ; p = t -> p ) {
if( p -> p != f )
   p -> d() != t -> d() ? rot( t ) : rot( p );
rot( t );
}
t -> upd();
}
 
Node* select( int k ) {
for( Node* t = root ; ; ) {
t -> relax();
int s = t -> ch[ 0 ] -> s;
if( k == s ) return t;
if( k > s )
   k -= s + 1 , t = t ->ch[ 1 ];
else 
   t = t -> ch[ 0 ];
}
}
 
Node* &get( int l , int r ) {
l-- , r++;
Node *L = select( l ) , *R = select( r );
splay( L );
splay( R , L );
return R -> ch[ 0 ];
}
 
Node* build( int l , int r ) {
if( l >= r ) return null;
int m = ( l + r ) >> 1;
Node* t = new Node( seq[ m ] );
t -> setc( build( l , m ) , 0 );
t -> setc( build( m + 1 , r ) , 1 );
t -> upd();
return t;
}
 
void ins() {
Node *L = select( pos ) , *R = select( pos + 1 );
splay( L ) , splay( R , L );
R -> setc( build( 1 , tot + 1 ) , 0 );
R -> upd();
L -> upd();
}
 
void del( Node* t ) {
if( t == null ) return;
rep( i , 2 ) del( t -> ch[ i ] );
Q.push( t );
}
 
void init() {
rep( i , maxnode ) Q.push( memory + i );
null = new Node( -inf );
null -> s = 0;
null -> sum = 0;
}
 
int main() {
// freopen( "test.in" , "r" , stdin );
// freopen( "test.out" , "w" , stdout );
init();
int n , m;
cin >> n >> m;
Rep( i , n ) scanf( "%d" , seq + i );
root = build( 0 , n + 2 );
char S[ 15 ];
while( m-- ) {
scanf( " %s" , S );
if( S[ 2 ] == 'X' ) {
Node* &t = get( 1 , n );
printf( "%d " , t -> mx );
} else {
scanf( "%d%d" , &pos , &tot );
if( S[ 0 ] == 'I' ) {
n += tot;
Rep( i , tot ) scanf( "%d" , seq + i );
ins();
} else if( S[ 0 ] == 'D' ) {
Node* &t = get( pos , pos + tot - 1 );
n -= tot;
del( t );
root -> ch[ 1 ] -> setc( null , 0 );
splay( root -> ch[ 1 ] );
} else if( S[ 0 ] == 'R' ) {
Node* &t = get( pos , pos + tot - 1 );
t -> Rev();
splay( t );
} else if( S[ 0 ] == 'M' ) {
Node* &t = get( pos , pos + tot - 1 );
int v;
scanf( "%d" , &v );
t -> Set( v );
splay( t );
} else if( S[ 0 ] == 'G' ) {
Node* &t = get( pos , pos + tot -1 );
printf( "%d " , t -> sum );
}
}
}
return 0;
}

------------------------------------------------------------------------ 

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 8501  Solved: 2563
[Submit][Status][Discuss]

Description

Input

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

HINT

Source

原文地址:https://www.cnblogs.com/JSZX11556/p/4590615.html