概念:线段树(Segment Tree)是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。对于线段树中的每一个非叶子节点[a,b],它的左子树表示的区间为[a,(a+b)/2],右子树表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树。叶节点数目为N,即整个线段区间的长度。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。——摘自维基百科
基本思路:把每个待处理的区间都拓展到完全二叉树最后一层的节点个数,形成完全二叉树,对于节点o,其左右子节点分别为o*2,o*2+1,叶子节点就是单个节点形成的区间,使用数组维护二叉树(简单高效)。
下面是在hiho oj网站涉及的所有线段树的题目及分析
思路:使用数组minv[i]维护结点编号为i的结点区间的最小值.
结点的区间在查询区间内则直接返回结点对应最小值minv[o],否则分别对结点的左右子树查询相应最小值,然后取左右子树的较小值作为最小值。
主要是针对修改结点涉及的区间对应结点的最小值信息进行维护。
思路:使用数组setv[i]维护区间设置的值,setv[o]>=0表明在o结点区间内的值都是setv[o],setv[o]=-1表明o所在区间的值不尽相同或者此区间没有数值。
如果setv[o]>=0则直接n*setv[o]计算到sum中,否则进入o的子节点计算在查询区间的和。
如果结点区间在修改区间内,则直接setv[o]=v,否则对子节点的在修改区间的结点赋值,同时如果setv[o]>0则要将该值传递给子节点,同时该节点的 setv[o]变为-1(因为该区间数值出现了不一致)。
思路:在这道题目是通过线段树结点将连续型区间离散化,并且将连续区间归一化,减少空间复杂度(预处理详见题目链接提示部分),然后进行区间修改,之后的算法同hiho20,只是需要考虑连续区间进行分解时比较特殊:
离散型:区间[l,r]分解为[l,m] [m+1,r]
连续性:区间[l,r]分解为[l,m] [m,r]
这里用了数组setv和sumv来维护区间值和区间和。所以查询操作直接返回sumv的第一个结点值就是总量,时间复杂度为O(1),对于两种修改操作首先明确:sumv[o] = sumv[2*o]+sumv[2*o+1].
原文地址:http://blog.csdn.net/barry283049/article/details/45827641