线段树和树状数组在很多时候都可以用来处理相同的问题,特别是在用来进行RMQ离线处理时候两者各有所长,故放在一起整理。
首先是线段树,线段树除了最后一层子节点整体是一颗标准的完全树,所以有着许多很有趣的特点,在区域搜索、区域数值增改中有着很大的优势,先上一道水题
poj3264 线段树
题意是对给出的Q次访问求出访问区间中数值的最大差值,正好与线段树的区间搜索相符。
本意是想用RMQ离线处理一下,但是因为本身不存在增改,离线处理也不会增加多少效率,所以就直接写了
#include
#include
#include
#include
#include
#include
#include
#include
#include
多校第四场hdu4638Group 线段树 + RMQ
题意是对给出访问求区域内能成立的组的个数(相邻点数之差为1可以加进一个组、一个数与相邻组存在差为1数的时候可以加入这个组)
因为组的情况不定,每次询问都要对线段树内的内容更新,这时就需要RMQ离线处理了,按照左位置或者右位置排序后按序处理整体输出
因为这样子写出出来好多变量与函数(有建树用的和离线运算一起更新所需要的变量与函数,按我的写法至少需要四个函数与十多个变量)写到后来很容易就乱了,以后需要好好研究怎么定义变量名以实现程序内容的清晰化。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
除去二维的,上面的就是线段树大多数的基本用法了,之后说说树状数组。
树状数组是基于二进制数做出来的数据访问的优化方法,所以每次定义的时候必须从1开始(线段树如果想用齐满树的特征来省变量也需要从1开始)
如果说线段树最大的优势是区间访问与更新,那树状数组最大的优势就是对单点的访问与更新。
同样以hdu4638Group为例,只要把中间的线段树部分改成了树状数组就可以了。
并且因为实际上这题都是对点更新所以时间效率还要高一点,但是和线段树有着同一个问题(树状数组有固有的lowbit函数与更新的update函数,与线段树的的建树update/maketree函数以及更新的cal/update正好凑成一对)函数变量很多,写的很晕。。
#include
#include
#include
#include
#include
#include
#include
#include
#include
总的来说,树状数组能处理的问题基本线段树都能处理,而线段树能处理的问题范围要比树状数组广,很多时候两者时间仅仅只是效率差而已,择优而用很重要~~^_^~~