线段树是一种灵活的数据结构,所谓的灵活是因为他的以有很多的变形,而具体的变形却还是有规律可言的 -
线段树是基于二分的,也就是可以在查找的时候优化复杂度为lgn ,而具体要考虑到的确是如何维护和通过维护什么来获得需要的结果;
1.求区间的最大值
当然可以用RMQ来求解 ;
线段树而言 : 考虑 , 对于区间的最大值,我们可以考虑,一个1~n的区间最大值a和1~n/2 与 n/2 ~ n的区间最大值b,c的关系 ;当然是a = max(b , c) ; 所以我们维护一个 max值t[i],每一次自顶向上pushup时 , t[rt] = max(t[rt<<1] , t[rt<<1|1] ); 就很容易就可以有线段树的代码 ;
2.求区间的和
同理可以使用树状数组 ;
线段树方法 : 考虑相同 , a = b + c ;
所以维护一个sum ,,t[rt] = t[rt<<1] + t[rt<<1|1] ;
以上两个通常用来优化复杂度 , 例如LIS 从 n^2 ---> nlgn ;
3.区间查找问题 : 模拟计算机分配内存在一段内存中找到第一个长为len的空间并且占用 ; 类似于hdu4553
维护一个max[rt]表示这段连续内存内的最大空闲内存 , xdl[rt] 表示此段内的最左边的空闲内存的右端点 ; xdr[rt] 表示最右段的左端点 ;
max[rt] = (xdl[rt<<1|1] - xdr[rt<<1] + 1 , max[rt<<1] , max[rt<<1|1] ) ;
xdl[rt] 和 xdr[rt] 也可以同样的维护 , 自己考虑;
综上所述 : 线段树的所需数据的更新维护才是建树时因该考虑的重点因素 ;
但是,如何想到用线段树来解决才是ACMer的解体突破口,后者比前者更重要 ;