传送门:【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 , ntypedef 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 线段树相关推荐

  1. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  2. HDU 1394 Minimum Inversion Number(线段树的单点更新)

    点我看题目 题意 :给你一个数列,a1,a2,a3,a4.......an,然后可以求出逆序数,再把a1放到an后,可以得到一个新的逆序数,再把a2放到a1后边,,,,,,,依次下去,输出最小的那个逆 ...

  3. hdu 5493 Queue(逆序对,线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5493 解题思路: 一道线段树的题目,因为是前面或者后面有k个比自己高的人,所以我们应该按照由身高从小到 ...

  4. 【HDU - 4217 】Data Structure? (线段树求第k小数)

    题干: Data structure is one of the basic skills for Computer Science students, which is a particular w ...

  5. HDU - 3564 Another LIS(LIS+线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=3564 题意 给出1~n的插入顺序,要求每次插入之后的LIS 分析 首先用线段树还原出最终序列.因为插入的顺序是按 ...

  6. 题解报告:hdu 1754 I Hate It(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某 ...

  7. HDU - 6070 Dirt Ratio (二分 + 线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题目大意:给定一个序列a,对于任何一个区间 [l,r],它的"Dirt Ratio&q ...

  8. HDU 6203 ping ping ping lca 线段树成段更新

    题目链接:HDU 6203 ping ping ping Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  9. HDU 5172 GTY's gay friends 线段树+前缀和+全排列

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5172 bc(中文): http://bestcoder.hdu.edu.cn/contes ...

最新文章

  1. mysql 硬盘写入速度_MySQL存储写入速度慢分析
  2. Qt Creator在属性之间添加绑定
  3. PrimeFaces 5.0 DataTable列切换器
  4. python标签控件是_Python 图形用户界面编程
  5. 高通:预计未来几年向苹果公司出售的芯片将减少
  6. Capsule:支持容器的JVM应用程序打包部署工具
  7. 使用HTML制作静态宠物网站——蓝色版爱宠之家(HTML+CSS)
  8. 鸿蒙系统安全模式,菜鸟必看 如何在安全模式下使用光驱
  9. 常见的Web服务器、应用服务器(Apache、tomcat、jetty、Nginx)简介及优缺点总结
  10. python如何将秒数转化成时分秒_python时分秒化为秒 python时分秒的正则表达式
  11. vmware 桥接 无线网卡 问题解决方案
  12. 苹果被曝重大系统漏洞:新款MacBook、iPhone 12统统波及,root权限秒被获取
  13. Linux 磁盘配额与VDO技术
  14. python 如何同时遍历两个列表
  15. linux 编码文件,linux文件编码
  16. delphi源码三层框架【框架简介】
  17. 【历史上的今天】8 月 15 日:苹果推出初代 iMac;谷歌收购摩托罗拉移动;Fuchsia 首次发布
  18. VS2010工程文件
  19. Android挂断电话流程
  20. mysql 联表 delete

热门文章

  1. 如何选型APS系统,还需明确这七大关键因素
  2. Dubbo相关问题如何用管程实现异步转同步?
  3. 程序员有哪些必备技能?
  4. 掌门教育市值再创新低:集体诉讼风险未解,近万名教师“无证”
  5. 计算机二级选择题瞎蒙,一级消防员考试,一级消防员考试题大全
  6. 蔡学镛[散文随笔]:从A到E+ (转)
  7. 如何让USB-C手机,电脑投屏到VR眼镜方案?还能同时实现充电?乐得瑞LDR6282 转接器方案
  8. 全球及中国游戏耳机市场运营模式分析及需求前景预测报告2022年版
  9. 分布式系统生成唯一主键
  10. 傅一平:运营商的大数据变现实践