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\n" , 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\n" , t -> sum );
}
}
}
return 0;
}
------------------------------------------------------------------------
1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 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
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
10
1
10
HINT
Source