【HDU】4942 Game on S♂play 线段树
2014-08-13 19:51
656 查看
传送门:【HDU】4942 Game on S♂play
题目分析:今天下午被这道题整死了,因为我的写法导致有的数可能变成负的,但是我们有察觉到,debug了一下午还是在吃饭的时候突然想到这个问题的。。。不过还好想到了,不然就没法AC了。。。。
题目中看似好多的旋转,但是,其实如果用中序遍历来看这棵树,那么无论怎么旋转他都还是一个顺序(这是中序遍历的特性),那么我们用中序遍历将树变成链,由于一个点的子树一定在链上的连续区间内,所以种种原因使得线段树可以大发神威。
我们需要维护每个节点对应的区间以及他的父亲,左右儿子,以及他和所有子节点的欢乐值之和。旋转的时候就更新一下节点信息,易知旋转最多改变两个点的信息,直接两次线段树单点更新搞定,最后查询就是普通的区间查询。
毫无坑点啊有木有!!!但是被我自己写出坑点来了。。。信息的加加减减由于一开始我取模了,是有可能得到负数的。。。这样结果明显会出错。。唉。。就因为这个逗比的错误调了一下午。。T U T
不过还是指针写起来比较美~还有不想再写非递归的了,过不了G++就过不了吧。。。反正算法对了
代码如下:
题目分析:今天下午被这道题整死了,因为我的写法导致有的数可能变成负的,但是我们有察觉到,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 ; }
相关文章推荐
- hdu 4942 Game on S♂play 线段树
- [线段树]HDU 4942——Game on S♂play
- hdu 4942 Game on S♂play(线段树)
- [Splay模拟 线段树 || Splay || LCT] HDU 4942 Game on S♂play
- HDU 4942 Game on S♂play(线段树、模拟、扩栈)
- [HDOJ 4942] Game on S♂play [线段树]
- 【线段树】 HDOJ 4942 Game on S♂play
- hdu4942 Game on S♂play【线段树 or LCT】
- 【平衡树->线段树】HDU4942[Game on S♂play]题解
- hdu 1116 Play on Words
- HDu--3935(I'll play a trick on you)
- HDU-1116-Play on Words (并查集+欧拉图)
- hdu 1116 Play on Words
- HDU 1564 Play a game
- HDU 1116 Play on Words
- hdu 1564 Play a game
- hdu 1116 Play on Words
- hdu1116 Play on Words(并查集)
- hdu 3953 I'll play a trick on you
- HDU 1116 Play on Words(有向图的欧拉路)