本文纯属原创,转载请注明出处,谢谢。
距离第一次接触线段树已经一年多了,再次参加ACM暑假集训,这一次轮到我们这些老家伙们给学弟学妹们讲解线段树了,所以就自己重新把自己做过的题目看了一遍,然后写篇博客纪念一下。作为一个菜鸟,文中肯定有很多表达不是很准确甚至错误的地方,欢迎各位大牛指正。
作为近年来算法竞赛里面最火爆的数据结构考点,它的用法和问法层出不穷。而作为解决反复对区间的更新和查询问题最好的数据结构,它拥有其他数据结构无法取代的地位。树状数组虽然也能解决很多问题,而且代码量较低,空间复杂度较低,但是局限性较大,比如区间最值的问题就不能用树状数组完美解决。
那么接下来就为大家带来线段树的两种基本用法:单点更新和区间更新(又叫成段更新)。
首先线段树它是一棵高度平衡的二叉树,那么很多二叉树的性质它是完美继承的,比如用数组去模拟的话,父节点的下标*2=左儿子的下标,父节点的下标*2+1=右儿子的下标。而这个性质也在线段树的实现中得到了很好的运用(当然线段树还有很多不同的写法,大家可以自行研究,这里不做展开)。
那么什么是线段树呢?
我们来看一道题:
这道题如果用常规暴力的做法,就把所有营地的士兵存在一个数组里面,然后对于每次操作直接更新对应位置的数,对于每次询问直接从i到j加起来。然而这么操作下来,对于极限数据50000个人,40000条命令,显然是会超时的,那么一种新的数据结构线段树就应运而生了。
首先第一个疑问:为什么线段树会快?
显然对于m个点n次询问,暴力的做法时间复杂度是O(m*n)的。然而线段树作为一棵二叉树,继承了二叉树O(logn)的优良品质,对于这道题最坏的复杂度也是O(m*logn)的,这个量显然是符合时间要求的。
第二:线段树如何处理?
倘若节点x(x为奇数)记录的是第1个点的数据,节点x+1记录的是第2个点的数据,那么节点x/2记录的就是区间[1,2]上的有效