基本線段樹

2021-08-15 17:52:25 字數 1362 閱讀 7463

作為乙個常用的資料結構,線段樹怎能不與玄學扯上關係。所以今天要講的是:玄學。

所謂線段樹,就是將乙個線段用數軸上的乙個點表示。

但是我當初就沒搞懂,所以我決定用我能理解的方法來講。

想象有一條線,嗯對,一條線段。

將這條線段從中點分開,中點歸左邊。

就這樣遞迴,遞迴,遞迴。

直到線段長度為1時,return;

好,這就是建樹的過程。

那你肯定要問,憑什麼要這樣寫。

別急,下面為你詳細解答。

以下為重點部分:

我們都知道,數軸上的區間覆蓋處理一直是個巨坑,乙個不小心就超時。

所以我們想出了線段樹這種輔助結構。

我們要找乙個長度為1的線段時,如果用線段樹,時間複雜度會是多少呢?

答案是:o(

logn

) o

(log⁡n

)我們來分析一下:

每一次遞迴後,待查詢線段的長度就成了父親線段長度的½

所以線段樹真的是乙個很高效的資料結構(某些情況下)

宣告:全部**將用c++語言完成

我們用結構體來儲存這棵樹

struct nodetree[6*maxn+5];
不知為何,我用4*maxn時總會re

先來建樹部分的**

void build(int number,int left,int right)
然後是查詢部分

void find(int number,int left,int right)..

.// 這裡並不是我偷懶,而是有問題要討論

}

在這裡我們發現了乙個問題——有兩種實現方式,分別是:

嚴謹認真,將左右端點依次與中點進行比較。

不管了,直接上,到時候不行再倒回來。

那麼大家覺得哪個是對的呢?猜一猜

選1的請舉手,恭喜你,你是對的

但是,它們兩個都是對的,時間複雜度也沒有什麼區別。

而且2碼起來還要簡單一些。

所以說。。。

選2的請舉手

原來你是大佬啊。雖然可能是蒙的

所以說,講了一大通廢話,也是時候該上**了。

我也準備了兩種**,隨大家喜好咯

方法1:

void find(int number,int

left,int

right)

方法2:

void find(int number,int

left,int

right)

線段樹基本操作(1)

建樹,查詢和單點修改 把一段長度為2 k的區間逐次對半分,可以總共分成2 k 1 1各節點,變成了一棵二叉樹 對於區間 lt,rt 它的子節點為區間 lt,mid 和區間 mid 1,rt 查詢時只要要查詢的區間的左右邊界剛好等於已知區間的邊界,就可以返回值了,不需要一搜到底 對於單點修改,基本上和...

線段樹基本操作(2)

假如指定乙個操作給一段區間的所有值加2,求任意區間的最小值 更新 才發現在change是就更改結點值而查詢時只釋放結點會更快,下面摘自網上 對於任意區間的修改,我們先按照查詢的方式將其劃分成線段樹中的結點,然後修改這些結點的資訊,並給這些結點標上代表這種修改操作的標記。在修改和查詢的時候,如果我們到...

線段樹的基本實現

線段樹是這樣一種結構,每個節點儲存陣列一部分的和 原陣列為13 57911 對應的線段樹結構如下 根節點是陣列之和,根節點的左孩子是陣列左半部分之和,根節點的右孩子是陣列右半部分數值之和。中間點 int mid start end 2 int left node 2 node 1 左子樹樹根 int...