BZOJ 1251: 序列终结者( splay )

先orz一下clj...我的splay跟着他写的...

这道题很普通的splay我调了这么久 T T , 就是因为 null 的值初始化为0 , 结果就挂了...

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

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
 
#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 = 50000 + 5;
const int maxnode = maxn + 10;
const int inf = 0x7fffffff;
 
int n;
 
struct Node *pt , *null;
 
struct Node { 
Node *ch[ 2 ] , *p;
int val , mx , add , size;
bool rev;
Node() : val( 0 ) , add( 0 ) , rev( 0 ) , mx( 0 ) {
ch[ 0 ] = ch[ 1 ] = null;
}
bool d() {
return this == p -> ch[ 1 ];
}
void setc( Node* c , int d ) {
ch[ d ] = c;
c -> p = this;
}
void Rev() {
rev ^= 1;
}
void Add( int ad ) {
add += ad;
val += ad;
mx += ad;
}
void upd() {
size = ch[ 0 ] -> size + ch[ 1 ] -> size + 1;
mx = max( val , max( ch[ 0 ] -> mx , ch[ 1 ] -> mx ) );
}
void relax() {
if( add ) {
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Add( add );
add = 0;
}
if( rev ) {
swap( ch[ 0 ] , ch[ 1 ] );
rep( i , 2 ) if( ch[ i ] != null ) 
   ch[ i ] -> Rev();
rev = false;
}
}
void* operator new( size_t ) {
return pt++;
}
};
 
Node NODE[ 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;
}
 
Node* select( int k ) {
for( Node* t = root ; ; ) {
t -> relax();
int s = t -> ch[ 0 ] -> size;
if( k == s ) return t;
else if( k > s ) {
k -= s + 1;
t = t -> ch[ 1 ];
} else 
   t = t -> ch[ 0 ];
}
}
 
void splay( Node* t , Node* f = null ) {
while( t -> p != f ) {
if( t -> p -> p == f ) rot( t );
else if( t -> d() != t -> p -> d() ) rot( t ) , rot( t );
else rot( t -> p ) , rot( t );
}
t -> upd();
}
 
Node* &get( int l , int r ) {
l-- , r++;
Node* L = select( l );
Node* R = select( r );
splay( L );
splay( R , L );
return R -> ch[ 0 ];
}
 
// [ l , r )
Node* build( int l , int r ) {
if( l >= r ) 
   return null;
int m = ( l + r ) >> 1;
Node* t = new( Node );
t -> setc( build( l , m ) , 0 );
t -> setc( build( m + 1 , r ) , 1 );
t -> upd();
return t;
}
 
void init() {
pt = NODE;
null = new( Node );
null -> size = 0;
null -> val = -inf;
null -> mx = -inf;
root = build( 0 , n + 2 );
root -> p = null;
}
 
int main() {
freopen( "test.in" , "r" , stdin );
freopen( "test.out" , "w" , stdout );
int m;
cin >> n >> m;
init();
while( m-- ) {
int op , L , R;
scanf( "%d%d%d" , &op , &L , &R );
Node* &t = get( L , R );
if( op == 1 ) {
int v;
scanf( "%d" , &v );
t -> Add( v );
splay( t );
} else if( op == 2 ) {
t -> Rev();
splay( t );
} else 
   printf( "%d\n" , t -> mx );
}
return 0;
}

  

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

1251: 序列终结者

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 2735  Solved: 1086
[Submit][Status][Discuss]

Description

网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。

Input

第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。

Output

对于每个第3种操作,给出正确的回答。

Sample Input

4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4

Sample Output

2
【数据范围】
N<=50000,M<=100000。

HINT

Source

 

posted @ 2015-06-15 21:56  JSZX11556  阅读(303)  评论(0编辑  收藏  举报