您的位置:首页 > 其它

【HDU】4942 Game on S♂play 线段树

2014-08-13 19:51 656 查看
传送门:【HDU】4942 Game on S♂play

题目分析:今天下午被这道题整死了,因为我的写法导致有的数可能变成负的,但是我们有察觉到,debug了一下午还是在吃饭的时候突然想到这个问题的。。。不过还好想到了,不然就没法AC了。。。。

题目中看似好多的旋转,但是,其实如果用中序遍历来看这棵树,那么无论怎么旋转他都还是一个顺序(这是中序遍历的特性),那么我们用中序遍历将树变成链,由于一个点的子树一定在链上的连续区间内,所以种种原因使得线段树可以大发神威。

我们需要维护每个节点对应的区间以及他的父亲,左右儿子,以及他和所有子节点的欢乐值之和。旋转的时候就更新一下节点信息,易知旋转最多改变两个点的信息,直接两次线段树单点更新搞定,最后查询就是普通的区间查询。

毫无坑点啊有木有!!!但是被我自己写出坑点来了。。。信息的加加减减由于一开始我取模了,是有可能得到负数的。。。这样结果明显会出错。。唉。。就因为这个逗比的错误调了一下午。。T U T

不过还是指针写起来比较美~还有不想再写非递归的了,过不了G++就过不了吧。。。反正算法对了

代码如下:

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

#pragma comment (linker,"/STACK:102400000,102400000") 

#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 )

#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid() ( ( l + r ) >> 1 )
#define root 1 , 1 , n

typedef long long LL ;

const int MAXN = 100005 ;
const int mod = 1e9 + 7 ;

struct Node {
	Node *c[2] , *f ;
	int size[2] ;//区间左右端点编号
	int idx ;//对应区间上的实际坐标
	LL v ;//以其为根的子树的欢乐值之和
	Node () : v ( 0 ) {}
} ;

struct Seg_Tree {
	Node node[MAXN] , *cur , *null ;
	int product[MAXN << 2] ;
	int val[MAXN] ;
	int n , m ;
	int cnt ;
	
	void dfs ( Node* o ) {
		if ( o -> c[0] != null ) dfs ( o -> c[0] ) ;
		o -> idx = ++ cnt ;
		o -> size[0] = o -> idx ;
		if ( o -> c[0] != null ) {
			o -> v += o -> c[0] -> v ;
			o -> size[0] = o -> c[0] -> size[0] ;
		}
		o -> size[1] = o -> idx ;
		if ( o -> c[1] != null ) dfs ( o -> c[1] ) ;
		if ( o -> c[1] != null ) {
			o -> v += o -> c[1] -> v ;
			o -> size[1] = o -> c[1] -> size[1] ;
		}
		val[o -> idx] = o -> v % mod ;
	}
	
	void update ( int pos , int v , int o , int l , int r ) {
		if ( l == r ) {
			product[o] = v ;
			return ;
		}
		int m = mid () ;
		if ( pos <= m ) update ( pos , v , lson ) ;
		else 		update ( pos , v , rson ) ;
		product[o] = ( LL ) product[ls] * product[rs] % mod ;
	}
	
	int query ( int L , int R , int o , int l , int r ) {
		if ( L <= l && r <= R ) return product[o] ;
		int m = mid () ;
		if ( R <= m ) return query ( L , R , lson ) ;
		if ( m <  L ) return query ( L , R , rson ) ;
		return ( LL ) query ( L , R , lson ) * query ( L , R , rson ) % mod ;
	}
	
	void build ( int o , int l , int r ) {
		if ( l == r ) {
			product[o] = val[l] ;
			return ;
		}
		int m = mid () ;
		build ( lson ) ;
		build ( rson ) ;
		product[o] = ( LL ) product[ls] * product[rs] % mod ;
	}
	
	void init () {
		cnt = 0 ;
		null = node ;
		cur = node + 1 ;
	}
	
	void rotate ( Node* o , int d ) {//旋转
		Node* c = o -> c[d ^ 1] ;
		Node* p = o -> f ;
		o -> v -= ( c -> v ) - ( c -> c[d] -> v ) ;
		c -> v += ( o -> v ) - ( c -> c[d] -> v ) ;
		o -> c[d ^ 1] = c -> c[d] ;
		c -> c[d] -> f = o ;
		c -> f = p ;
		if ( p != null ) {
			if ( o == p -> c[0] ) p -> c[0] = c ;
			else p -> c[1] = c ;
		}
		c -> c[d] = o ;
		o -> f = c ;
	}
	
	void solve () {
		int d , x ;
		int w , l , r ;
		init () ;
		scanf ( "%d%d" , &n , &m ) ;
		cur -> f = null ;
		FOR ( i , 1 , n ) {
			scanf ( "%d%d%d" , &w , &l , &r ) ;
			cur -> v = w ;
			cur -> c[0] = node + l ;
			cur -> c[1] = node + r ;
			if ( l ) cur -> c[0] -> f = node + i ;
			if ( r ) cur -> c[1] -> f = node + i ;
			++ cur ;
		}
		dfs ( node + 1 ) ;
		build ( root ) ;
		while ( m -- ) {
			scanf ( "%d%d" , &d , &x ) ;
			Node* o = node + x ;
			if ( d < 2 ) {
				Node* c = o -> c[d] ;
				if ( c == null ) continue ;
				c -> size[d ^ 1] = o -> size[d ^ 1] ;
				if ( c -> c[d ^ 1] != null ) o -> size[d] = c -> c[d ^ 1] -> size[d] ;
				else o -> size[d] = o -> idx ;
				rotate ( o , d ^ 1 ) ;
				update ( o -> idx , o -> v % mod , root ) ;
				update ( c -> idx , c -> v % mod , root ) ;
			} else {
				printf ( "%d\n" , query ( o -> size[0] , o -> size[1] , root ) ) ;
			}
		}
	}
} T ;

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