欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)開(kāi)點(diǎn)線(xiàn)段樹(shù)詳解

 更新時(shí)間:2025年02月26日 08:15:41   作者:MelonTe  
線(xiàn)段樹(shù)是一種用于高效處理區(qū)間查詢(xún)和區(qū)間更新的數(shù)據(jù)結(jié)構(gòu),下面我們就來(lái)看看如何使用Go實(shí)現(xiàn)動(dòng)態(tài)開(kāi)點(diǎn)線(xiàn)段樹(shù)的方式,感興趣的可以了解下

1、線(xiàn)段樹(shù)介紹

線(xiàn)段樹(shù)是一種用于高效處理區(qū)間查詢(xún)和區(qū)間更新的數(shù)據(jù)結(jié)構(gòu),當(dāng)我們需要解決一個(gè)頻繁更新區(qū)間值的問(wèn)題的時(shí)候,就可以采用線(xiàn)段樹(shù)的結(jié)構(gòu)進(jìn)行解決。線(xiàn)段樹(shù)的核心思想是將區(qū)間分為多個(gè)子區(qū)間進(jìn)行管理,越往下區(qū)間范圍越小,根節(jié)點(diǎn)表示整個(gè)線(xiàn)段樹(shù)能表示的區(qū)間。

本文記錄使用Go實(shí)現(xiàn)動(dòng)態(tài)開(kāi)點(diǎn)線(xiàn)段樹(shù)的方式,該模板的線(xiàn)段樹(shù)用于解決區(qū)間求和問(wèn)題,還有求解區(qū)間最小值、最大值的線(xiàn)段樹(shù)可以進(jìn)行微調(diào)修改即可。

區(qū)間查詢(xún)、區(qū)間更新的時(shí)間復(fù)雜度均為O(logN)。

2、動(dòng)態(tài)開(kāi)點(diǎn)線(xiàn)段樹(shù)實(shí)現(xiàn)

動(dòng)態(tài)開(kāi)點(diǎn)的核心在于,需要縮小范圍,即進(jìn)入子節(jié)點(diǎn)的時(shí)候再進(jìn)行創(chuàng)建,相對(duì)于使用數(shù)組來(lái)實(shí)現(xiàn)線(xiàn)段樹(shù),可以更大的減小空間開(kāi)銷(xiāo)。

線(xiàn)段樹(shù)節(jié)點(diǎn)

一個(gè)節(jié)點(diǎn)需要記錄它的左子節(jié)點(diǎn)、右子節(jié)點(diǎn)、當(dāng)前節(jié)點(diǎn)表示的區(qū)間的和val,以及暫未下推給子節(jié)點(diǎn)的懶惰值lazy。

type SegTreeNode struct {
    lazy  int
    val   int
    left  *SegTreeNode
    right *SegTreeNode
}

線(xiàn)段樹(shù)的創(chuàng)建

整個(gè)線(xiàn)段樹(shù)只需要記錄一個(gè)根節(jié)點(diǎn)以及該線(xiàn)段樹(shù)表示的區(qū)間上屆。

type SegTree struct {
    //線(xiàn)段樹(shù)的范圍,0~N
    N    int
    root *SegTreeNode
}
 
// 創(chuàng)建線(xiàn)段樹(shù)
func CreateSegTree(n int) *SegTree {
    return &SegTree{
        N: n,
        root: &SegTreeNode{
            lazy:  0,
            val:   0,
            left:  nil,
            right: nil,
        },
    }
}

遞歸上推

當(dāng)更新完了子節(jié)點(diǎn)后,回到當(dāng)前節(jié)點(diǎn)的時(shí)候,需要更新當(dāng)前節(jié)點(diǎn)的值,表示從樹(shù)的底部上推值。

// 遞歸上推
func (ST *SegTree) Pushup(node *SegTreeNode) {
    node.val = node.left.val + node.right.val
}

懶惰下推

當(dāng)需要縮小查找區(qū)間的時(shí)候,需要向下查找,這時(shí)候要先把懶惰值下推,防止查找出錯(cuò)誤的結(jié)果,也防止子節(jié)點(diǎn)還未創(chuàng)建。

// 同步下推
func (ST *SegTree) Pushdown(node *SegTreeNode, leftnum, rightnum int) {
    //創(chuàng)建左右節(jié)點(diǎn)
    if node.left == nil {
        node.left = new(SegTreeNode)
    }
    if node.right == nil {
        node.right = new(SegTreeNode)
    }
    //下推節(jié)點(diǎn)懶惰標(biāo)記
    if node.lazy == 0 {
        return
    }
    node.left.val += leftnum * node.lazy
    node.right.val += rightnum * node.lazy
    //下推
    node.left.lazy += node.lazy
    node.right.lazy += node.lazy
    //置零
    node.lazy = 0
}

首先先創(chuàng)建左右節(jié)點(diǎn),如果沒(méi)有需要下推的懶惰標(biāo)記則直接返回。否則就更新左右節(jié)點(diǎn)的val和lazy。

更新操作

// 更新操作,更新[left,right]區(qū)間的值,start和end是當(dāng)前處在區(qū)間
func (ST *SegTree) Update(node *SegTreeNode, start, end, left, right, val int) {
    if left <= start && end <= right {
        //鎖定區(qū)間,進(jìn)行更新
        node.val += (end - start + 1) * val
        node.lazy += val
        return
    }
    //縮小區(qū)間
    mid := (start + end) / 2
    //需要找到子節(jié)點(diǎn),先下推懶惰標(biāo)記
    ST.Pushdown(node, mid-start+1, end-mid)
    if mid >= left {
        ST.Update(node.left, start, mid, left, right, val)
    }
    if mid+1 <= right {
        ST.Update(node.right, mid+1, end, left, right, val)
    }
    //遞歸
    ST.Pushup(node)
}

left和right表示要更新的區(qū)間,而start和end表示當(dāng)前區(qū)間。如果當(dāng)前區(qū)間處在需要更新的區(qū)間內(nèi),則直接更新區(qū)間值以及懶惰值,然后直接返回即可,此時(shí)不需要繼續(xù)更新下面節(jié)點(diǎn)的值,這是動(dòng)態(tài)開(kāi)點(diǎn)的關(guān)鍵所在。

若當(dāng)前區(qū)間并未完全處在需要更新的區(qū)間內(nèi),則二分該區(qū)間,縮小范圍進(jìn)行更新。

例如在一次操作需要更新的是[30,40]范圍的值,而當(dāng)前區(qū)間處在[25,50]中,當(dāng)前區(qū)間并未完全處在更新區(qū)間,則二分為[25,37]和[38,50],左區(qū)間和右區(qū)間均和需要更新的區(qū)間存在交集,那么就往下更新,直到更新區(qū)間包含當(dāng)前區(qū)間。

在更新完后,進(jìn)行一次上推。

查詢(xún)操作

與更新操作類(lèi)似,只需要一個(gè)ans來(lái)記錄答案并且返回。

// 查詢(xún)操作,返回區(qū)間的值
func (ST *SegTree) Query(node *SegTreeNode, start, end, left, right int) int {
    if left <= start && end <= right {
        return node.val
    }
    mid := (start + end) / 2
    ST.Pushdown(node, mid-start+1, end-mid)
    ans := 0
    if left <= mid {
        ans += ST.Query(node.left, start, mid, left, right)
    }
    if mid+1 <= right {
        ans += ST.Query(node.right, mid+1, end, left, right)
    }
    return ans
}

到此這篇關(guān)于Go語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)開(kāi)點(diǎn)線(xiàn)段樹(shù)詳解的文章就介紹到這了,更多相關(guān)Go線(xiàn)段樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go-cqhttp環(huán)境配置及安裝過(guò)程

    go-cqhttp環(huán)境配置及安裝過(guò)程

    這篇文章主要介紹了go-cqhttp環(huán)境配置,包括go-cqhttp安裝及簡(jiǎn)單介紹,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • Go語(yǔ)言中三個(gè)輸入函數(shù)(scanf,scan,scanln)的區(qū)別解析

    Go語(yǔ)言中三個(gè)輸入函數(shù)(scanf,scan,scanln)的區(qū)別解析

    本文詳細(xì)介紹了Go語(yǔ)言中三個(gè)輸入函數(shù)Scanf、Scan和Scanln的區(qū)別,包括用法、功能和輸入終止條件等,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • Go簡(jiǎn)單實(shí)現(xiàn)協(xié)程方法

    Go簡(jiǎn)單實(shí)現(xiàn)協(xié)程方法

    本文主要介紹了Go簡(jiǎn)單實(shí)現(xiàn)協(xié)程的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-12-12
  • go語(yǔ)言切片去重的3種方式

    go語(yǔ)言切片去重的3種方式

    go語(yǔ)言中的切片是使用非常頻繁的一個(gè)數(shù)據(jù)結(jié)構(gòu),本文主要介紹了go語(yǔ)言切片去重的3種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Go語(yǔ)言異常處理error、panic、recover的使用

    Go語(yǔ)言異常處理error、panic、recover的使用

    GO語(yǔ)言中引入的異常的處理方式為error、panic、recover ,本文主要介紹了Go語(yǔ)言異常處理error、panic、recover的使用,感興趣的可以了解一下
    2024-08-08
  • 淺談Golang內(nèi)存逃逸

    淺談Golang內(nèi)存逃逸

    本文主要介紹了Golang內(nèi)存逃逸,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • go語(yǔ)言編程實(shí)現(xiàn)遞歸函數(shù)示例詳解

    go語(yǔ)言編程實(shí)現(xiàn)遞歸函數(shù)示例詳解

    這篇文章主要為大家介紹了go語(yǔ)言編程實(shí)現(xiàn)遞歸函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例

    Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例

    這篇文章主要介紹了Golang Cron 定時(shí)任務(wù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • go json編譯原理XJSON實(shí)現(xiàn)四則運(yùn)算

    go json編譯原理XJSON實(shí)現(xiàn)四則運(yùn)算

    這篇文章主要為大家介紹了go json編譯原理XJSON實(shí)現(xiàn)四則運(yùn)算示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • go語(yǔ)言面試如何實(shí)現(xiàn)自旋鎖?

    go語(yǔ)言面試如何實(shí)現(xiàn)自旋鎖?

    這篇文章主要為大家介紹了go語(yǔ)言面試中常問(wèn)的如何實(shí)現(xiàn)自旋鎖問(wèn)題實(shí)例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11

最新評(píng)論