作為乙個常用的資料結構,線段樹怎能不與玄學扯上關係。所以今天要講的是:玄學。
所謂線段樹,就是將乙個線段用數軸上的乙個點表示。
但是我當初就沒搞懂,所以我決定用我能理解的方法來講。
想象有一條線,嗯對,一條線段。
將這條線段從中點分開,中點歸左邊。
就這樣遞迴,遞迴,遞迴。
直到線段長度為1時,return;
好,這就是建樹的過程。
那你肯定要問,憑什麼要這樣寫。
別急,下面為你詳細解答。
以下為重點部分:
我們都知道,數軸上的區間覆蓋處理一直是個巨坑,乙個不小心就超時。
所以我們想出了線段樹這種輔助結構。
我們要找乙個長度為1的線段時,如果用線段樹,時間複雜度會是多少呢?
答案是:o(
logn
) o
(logn
)我們來分析一下:
每一次遞迴後,待查詢線段的長度就成了父親線段長度的½
所以線段樹真的是乙個很高效的資料結構(某些情況下)
宣告:全部**將用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...