您的位置:首页 > 其它

【BZOJ】1500 [NOI2005]维修数列 【splay】

2014-09-30 22:23 429 查看
传送门:【BZOJ】1500 [NOI2005]维修数列

题目分析:题目很简单,就维护左连续最大和,右连续最大和,以及区间最大和,区间和,是否反转,是否被置为相同即可。

一开始漏考虑了翻转的时候左右连续最大和也要翻转,还有就是区间最大和可能等于自身。。

明明很简单的题。。却调了那么久。。不说了。。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std ;

typedef long long LL ;

#pragma comment(linker, "/STACK:16777216")
#define Log( i , a , b ) for ( int i = a ; ( 1 << i ) <= b ; ++ i )
#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 travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )

const int MAXN = 1000005 ;
const int INF = 100000000 ;

struct Node* null ;
struct Node* root ;

struct Node {
	Node* f ;
	Node* c[2] ;
	int v ;
	int s ;
	int sum ;
	int Lmax ;
	int Mmax ;
	int Rmax ;
	int flip ;
	int same ;
	
	inline int max ( const int& a , const int& b ) {
		if ( a > b ) return a ;
		return b ;
	}
	
	inline int max ( const int& a , const int& b , const int& c ) {
		if ( a > b ) {
			if ( a > c ) return a ;
			return c ;
		} else {
			if ( b > c ) return b ;
			return c ;
		}
	}
	
	inline void newnode ( Node* fa , int val ) {
		s = 1 ;
		f = fa ;
		same = flip = 0 ;
		c[0] = c[1] = null ;
		v = sum = Lmax = Mmax = Rmax = val ;
	}
	
	inline void link_child ( Node* o , int d ) {
		c[d] = o ;
		o->f = this ;
	}
	
	inline void make_flip () {
		if ( this == null ) return ;
		swap ( c[0] , c[1] ) ;
		swap ( Lmax , Rmax ) ;
		flip ^= 1 ;
	}
	
	inline void make_same ( int val ) {
		if ( this == null ) return ;
		v = val ;
		same = 1 ;
		sum = s * v ;
		Lmax = Rmax = Mmax = max ( v , sum ) ;
	}
	
	void push_up () {
		s = c[0]->s + 1 + c[1]->s ;
		sum = c[0]->sum + v + c[1]->sum ;
		Lmax = max ( c[0]->Lmax , c[0]->sum + v , c[0]->sum + v + c[1]->Lmax ) ;
		Rmax = max ( c[1]->Rmax , c[1]->sum + v , c[1]->sum + v + c[0]->Rmax ) ;
		Mmax = max ( v , c[0]->Mmax , c[1]->Mmax ) ;//这里忘记Mmax可能等于v了,WA死。。
		Mmax = max ( Mmax , max ( c[0]->Rmax + v , c[1]->Lmax + v ) , c[0]->Rmax + v + c[1]->Lmax ) ;
	}
	
	void push_down () {
		if ( flip ) {
			c[0]->make_flip () ;
			c[1]->make_flip () ;
			flip = 0 ;
		}
		if ( same ) {
			c[0]->make_same ( v ) ;
			c[1]->make_same ( v ) ;
			same = 0 ;
		}
	}
	
	void sign_down () {
		if ( f != null ) f->sign_down () ;
		push_down () ;
	}
	
	void rotate ( int d ) {
		Node* p = f ;
		Node* gp = f->f ;
		p->link_child ( c[d] , !d ) ;
		if ( gp != null ) gp->link_child ( this , p == gp->c[1] ) ;
		else f = null ;
		link_child ( p , d ) ;
		p->push_up () ;
	}
	
	void splay ( Node* r = null ) {
		sign_down () ;
		while ( f != r ) {
			if ( f->f == r ) {
				this == f->c[0] ? rotate ( 1 ) : rotate ( 0 ) ;
			} else {
				if ( f == f->f->c[0] ) {
					this == f->c[0] ? f->rotate ( 1 ) : rotate ( 0 ) ;
					rotate ( 1 ) ;
				} else {
					this == f->c[1] ? f->rotate ( 0 ) : rotate ( 1 ) ;
					rotate ( 0 ) ;
				}
			}
		}
		push_up () ;
		if ( r == null ) root = this ;
	}
} ;

struct Splay {
	Node node[MAXN] ;
	Node* cur ;
	Node* pool[MAXN] ;
	int top ;
	
	void push_back ( Node* o ) {
		if ( o == null ) return ;
		pool[top ++] = o ;
		push_back ( o->c[0] ) ;
		push_back ( o->c[1] ) ;
	}
	
	void select ( int kth , Node* r ) {
		++ kth ;
		Node* o = root ;
		while ( o != null ) {
			o->push_down () ;
			int s = o->c[0]->s ;
			if ( s + 1 == kth ) break ;
			if ( kth <= s ) o = o->c[0] ;
			else o = o->c[1] , kth -= s + 1 ;
		}
		o->splay ( r ) ;
	}
	
	Node* get ( int l , int r ) {
		select ( l - 1 , null ) ;
		select ( r + 1 , root ) ;
		return root->c[1]->c[0] ;
	}
	
	void reverse ( int l , int r ) {
		Node* o = get ( l , r ) ;
		o->make_flip () ;
		o->splay () ;
	}
	
	void set ( int l , int r , int val ) {
		Node* o = get ( l , r ) ;
		o->make_same ( val ) ;
		o->splay () ;
	}
	
	void remove ( int l , int r ) {
		Node* o = get ( l , r ) ;
		root->c[1]->c[0] = null ;
		root->c[1]->push_up () ;
		root->push_up () ;
		push_back ( o ) ;
	}
	
	void insert ( Node* o , int pos ) {
		get ( pos + 1 , pos ) ;
		root->c[1]->link_child ( o , 0 ) ;
		root->c[1]->push_up () ;
		root->push_up () ;
		o->splay () ;
	}
	
	void query_sum ( int l , int r ) {
		printf ( "%d\n" , get ( l , r )->sum ) ;
	}
	
	void query_max_sum () {
		printf ( "%d\n" , root->Mmax ) ;
	}
	
	Node* make_new_tree ( int num[] , int n ) {
		Node* x = null ;
		Node* o = null ;
		For ( i , 1 , n ) {
			if ( top ) o = pool[-- top] ;
			else o = cur ++ ;
			o->newnode ( null , num[i] ) ;
			o->link_child ( x , 0 ) ;
			o->push_up () ;
			x = o ;
		}
		return o ;
	}
	
	void clear () {
		top = 0 ;
		cur = node ;
		null = cur ++ ;
		null->newnode ( null , -INF ) ;
		null->s = 0 ;
		null->sum = 0 ;
		root = cur ++ ;
		root->newnode ( null , -INF ) ;
		root->c[1] = cur ++ ;
		root->c[1]->newnode ( root , -INF ) ;
		root->push_up () ;
	}
} S ;

int num[MAXN] ;
char op[20] ;
int n , m ;

void solve () {
	int pos , tot , x ;
	S.clear () ;
	For ( i , 1 , n ) scanf ( "%d" , &num[i] ) ;
	Node* o = S.make_new_tree ( num , n ) ;
	S.insert ( o , 0 ) ;
	while ( m -- ) {
		scanf ( "%s" , op ) ;
		if ( op[0] == 'I' ) {
			scanf ( "%d%d" , &pos , &tot ) ;
			For ( i , 1 , tot ) scanf ( "%d" , &num[i] ) ;
			Node* o = S.make_new_tree ( num , tot ) ;
			S.insert ( o , pos ) ;
		} else if ( op[0] == 'D' ) {
			scanf ( "%d%d" , &pos , &tot ) ;
			S.remove ( pos , pos + tot - 1 ) ;
		} else if ( op[2] == 'K' ) {
			scanf ( "%d%d%d" , &pos , &tot , &x ) ;
			S.set ( pos , pos + tot - 1 , x ) ;
		} else if ( op[0] == 'R' ) {
			scanf ( "%d%d" , &pos , &tot ) ;
			S.reverse ( pos , pos + tot - 1 ) ;
		} else if ( op[0] == 'G' ) {
			scanf ( "%d%d" , &pos , &tot ) ;
			S.query_sum ( pos , pos + tot - 1 ) ;
		} else S.query_max_sum () ;
	}
}

int main () {
	while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
	return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: