var sum []int
var lazyT[]int
var arr[]int
//改变了区间中某一个值或某些值时,我们需要沿着线段树向上更新改变值的节点与根节点间的所有值,可以看出这部操作与线段树的高度有关,复杂度为O(logn)
func pushUp(idx int){
sum[idx]=sum[idx*2]+sum[idx*2+1]
}
//build
func build(left,right,idx int){
if left==right{
//单节点
sum[idx]=arr[left]
return
}
var mid=left+(right-left)/2
build(left,mid,idx*2)
build(mid+1,right,idx*2+1)
pushUp(idx)
}
//单点修改。改变区件中的某一个值,即在树中找到对应的叶节点,更新其值,然后递归改变该节点到根节点路径上所有节点的值
func updatePoint(changedIdx,changedValue,left,right,idx int){
if left==right{
//单节点
sum[idx]+=changedValue
return
}
var mid=left+(right-left)/2
if changedIdx<=mid{
updatePoint(changedIdx,changedValue,left,mid,idx*2)
}else{
updatePoint(changedValue,changedValue,mid+1,right,idx*2+1)
}
pushUp(idx)//子节点更新了,所以本节点也需要更新信息
}
//区间修改,在区间修改的时候我们引入一个新的概念——懒惰标记
//
//懒惰标记:表示本节点的统计信息已经根据标记更新过了,但是本节点的子节点还没有更新
//
func pushDown(idx,leftNum,rightTree int){
//leftNum,rightTree 左子树,右子树的数字数量
//懒惰标记下推
if lazyT[idx]>0{
lazyT[idx*2]+=lazyT[idx]
lazyT[idx+2+1]+=lazyT[idx]
sum[idx*2]+=lazyT[idx]*leftNum
sum[idx*2+1]+=lazyT[idx]*rightTree
lazyT[idx]=0//清除本节点标记
}
}
func updateSeg(changedLeftIdx,changedRightIdx, changedValue, left, right,idx int) {
if changedLeftIdx<=left&&right<=changedRightIdx{
//如果本区间完全在操作区间[L,R]以内
sum[idx]+=changedValue*(right-left+1)
lazyT[idx]+=changedValue增加lazyT标记,表示本区间的Sum正确,子区间的Sum仍需要根据lazyT的值来调整
}
var mid=left+(right-left)/2
pushDown(idx,mid-left+1,right-mid)
if changedLeftIdx<=mid{
updateSeg(changedLeftIdx,changedRightIdx,changedValue,left,mid,idx*2)
}
if changedRightIdx>mid{
updateSeg(changedLeftIdx,changedRightIdx,changedValue,mid+1,right,idx*2+1)
}
pushUp(idx)//更新本节点信息
}
//查询,查询过程中有一个很重要的操作便是懒惰标记的下推,理解了懒惰标记的下推,查询操作就很好理解
func query(queryLeft,queryRight, left, right, idx int)int{
if queryLeft<=left&&right<=queryRight{
//在区间[L,R]以内
return sum[idx]
}
var mid=left+(right-left)/2
pushDown(idx,mid-left+1,right-mid)
var res int
if queryLeft<=mid{
res+=query(queryLeft,queryRight,left,mid,idx*2)
}
if queryRight>mid{
res+=query(queryLeft,queryRight,mid+1,right,idx*2+1)
}
return res
}
线段树GO实现
最新推荐文章于 2022-06-29 11:22:02 发布