从零到树状数组&线段树
总想着总结下总咕咕了,
今天来填坑了, 总结下树状数组和线段树,
此文顺便全方面对比树状数组与线段树, 并加以题目验证
客观对比树状数组, 线段树 ( 再次体验树状数组的优雅
由于各种原因(懒), 这里的从零开始指的是理解线段树和树状数组基础
持续跟新中...
单点修改, 区间求和
基础操作, 直接上例题吧
题意: 单点修改,区间求和
题解:树状数组优势项目, 主要代码就四五行,
树状数组就用lowbit进行区间跳跃, 进行修改和求和
这里用时间戳做了个小优化,达成清空数组的效果
1 | struct BitTree{ |
线段树就用建树之后正常修改和查询即可
1 | struct SegTree{ |
solution1:
1 | /********************************************************* |
solution2:
1 | /********************************************************* |
单点修改, RMQ
线段树无脑项目,改改查询就行
1 | struct SegTree{ |
树状数组得来些优雅操作
直接搞?
1 | void add(int pos, int val){ |
明显,初始构建时是可行的,但遇到后续修改的时候就出现问题了,每次都清空构建O(n * m * log(n))不现实
众所周知,lowbit保留了二进制下的最后一个一, 那么所能对当前数造成影响的所有数的下标是能通过加上那个一得到当前数下标的那些
也就是说 1001000, 能对他造成影响的只有
1000100 + lowbit(1000100) = 1000100 + 100 = 1001000
1000110 + lowbit(1000110) = 1000110 + 10 = 1001000
1000111 + lowbit(1000111) = 1000111 + 1 = 1001000
看到这儿, 你琢磨了一会, 发现, 不就是这样吗!
能影响当前数的不就是 \(x - 2^0, x - 2^1 ... x - 2^n\) (\(2^n < lowbit(x)\)) 吗?
于是一个O(log^2 n)的更新就诞生了
1 | void add(int pos, int val){ |
下面进行查询, 寻常树状数组的查询的东西都是带有可减性的,在这儿的最值可没有,
那么就从右边往坐跳, 如果跳了会出去,那么我就一个个看
1 | void qMax(int l, int r){ |
这样, 你就得到了一个O(log^2 n)的查询
1 | struct BitTree{ |
接下来上题吧
solution1:
1 | /********************************************************* |
solution2:
1 | /********************************************************* |