簡單的樹狀陣列

2022-02-08 23:13:39 字數 2377 閱讀 9730

目錄對結構的探索—引

zkw 線段樹介紹

對結構的探索 —— 續

小結future

當然我不可能把所有知識**羅列, 希望我的文字會給你帶來一些啟發和消遣。

單單拿出樹狀陣列來說的話, 可以說它是乙個利用某些數列資訊的區間可並性, 平衡數列單點修改和字首查詢時間複雜度的資料結構, 乙個樹狀陣列維護乙個數列的資訊。

樹狀陣列的最重要的主體是數列下標(1~n), 它就是整個結構。

將乙個數二進位制分解: \((a)_ = (b_1b_2\cdots b_k)_2\) , 定義 \(lowbit[(b_1b_2\cdots b_k)_2]\) 就是乙個最大的 \(2^j\) 滿足 \(b_j=1, \quad \forall p\in[j+1,k], \quad b_p=0\)。

在樹狀陣列裡, 乙個下標 t 就代表原數列下標在 \([t-lowbit(t)+1, t]\) 之間所有數的資訊的並。

所以樹狀陣列的查詢操作就很好寫了, 不斷減 lowbit 不斷合併資訊就行了。

對於單點修改, 要找出原數列中乙個數能影響的樹狀陣列中的下標, 然後逐一修改。

對於數字 \(a\)、\(b\), \(a \in [b-lowbit(b)+1, b]\), 那麼首先 \(a\le b\), 再次 \(b-lowbit(b)+1 \le a\), 在 \(a\le b\) 的前提下, 後乙個條件要滿足, 首先必須 \(lowbit(b) \ge lowbit(a)\), 再次, 從高位往低位比, b 比 a 高的第一位一定是 lowbit(b)。由此可以很輕鬆地證明樹狀陣列的修改演算法。

將問題化簡為 「尋找乙個最小的 x, 使得 sum[1,x] <= k」。

這個問題顯然是有單調性的, 就像 倍增lca求lca的過程 一樣求好了。

追究原理?挺簡單的, 很多演算法也有在用, 自己看一下吧。

主要用於防止超多 clear 暴斃, 增加了查詢修改的常數(只有一點點)但是使得 clear 複雜度變成 \(o(1)\)。

主要是給每個節點加乙個時間戳, 不符合當前時間就初始化節點。

if 語句的分支**造成的損失可以通過三目運算子規避。

只是想隨便 yy 以下,不知道有沒有用。

合併複雜度必然不低於 \(o(n)\), 然而有 \(o(n)\) 建樹狀陣列的演算法……

完全不需要考慮怎麼合併嘛。

然而複雜度上界也是 \(o(n)\) 的, 完全沒必要思考嘛。

樸素的插入要 o(n log n), 樹狀陣列只有 o(n) 個節點。

對於乙個包含了 [l,r] 區間的節點, 有 r-l+1 個節點的插入要經過它。

由於資訊的可並性, 可以直接這麼寫:

for(int i=1;i<=n;++i)

只靠 \(fa[x] = x + lowbit(x)\) 的話,這是乙個分形的, 怪異的結構。

把所有 fa 去掉, 發現是乙個優美的沒有右兒子的線段樹結構。

講稿《統計的力量——線段樹》 by zkw

一顆滿二叉樹, 根節點為 1, 對於節點 x, ls(x) = x<<1, rs(x) = x<<1|1。

把節點標號換成二進位制, 這顆滿二叉樹就是 01 trie, 二叉堆的經典寫法用這種結構, 線段樹的經典寫法也是用這種結構。(我超喜歡動態開點線段樹

zkw 線段樹就是利用這種滿二叉樹的性質, 提高尋找某段區間是有哪些區間並起來的效率的演算法。

預處理 可以用歸納法證明, 滿二叉樹的葉節點去掉 highbit, 就是對應的原數列中的下標。

樸素探索

對於乙個詢問 \([l,r]\), 它一定可以被拼出來嘛?當然可以, 用葉節點……

那麼它的最簡拼接是什麼?

首先乙個節點的右子節點一定是奇數的, 左子節點一定是偶數的。

考慮先找出 l、r 所對應的葉子節點。

考慮縮小詢問區間, 若 l 為奇數, 那麼顯然這個 \(l\) 可以先加上, 然後縮小詢問區間;同樣的, 若 r 為偶數, 那麼這個 r 可以先加上, 然後縮小詢問區間。

推廣一下, 若 l 代表的節點(不一定是葉子節點)是奇數, 那麼把 l 先加上, 然後縮小詢問區間, 同樣的, 對 r 也有類似處理方法。

為什麼可以這樣做? 因為此時 l(或 r) 所代表的節點一定是最簡拼接中的節點。

之後如何縮小詢問區間呢?若已經加上了, 則變成父節點的兄弟, 否則變成父節點。

什麼時候結束?等到 l>r 就行了。

題解:詢問區間改成開區間

如果把詢問的閉區間改成開區間, 然後按照閉區間的葉子節點不斷往上走, 可以發現每次停頓的兄弟節點就是要找的區間節點, 這個可以很輕鬆證明。

迭代停止的條件也將變成兩個節點變成兄弟節點

參考zkw 的講稿吧。

樹狀陣列結構的研究可以從滿二叉樹的性質入手。

教練,我想學 leafy tree

樹狀陣列簡單入門

樹狀陣列是乙個查詢和修改複雜度都為log n 的資料結構。主要用於查詢任意兩位之間的所有元素之和。但是每次只能修改乙個元素的值,不如線段樹的應用範圍廣,但是寫起來比線段樹簡單很多,空間複雜度也會低一點。可以用來解一些像求逆序數的題。上面這張圖就表示了樹狀陣列與原陣列的關係 c陣列完整的儲存了a的所有...

對樹狀陣列的 簡單 理解

當時學資料結構的時候,暑假訓練的課上得雲裡霧裡,自己還忙於補之前的題,導致只聽完了課,內容都沒有消化.學完了樹狀陣列,只知道怎麼用,該用的時候還想不起來用.現在細想一下,簡單的樹狀陣列就是 點修改 區間查詢,能降一位o n 到log n 現在有乙個序列,a n 假設n 16.設 c 1 a 1 c ...

樹狀陣列簡單易懂的詳解

樹狀陣列確實是個好東西啊,以前搞比賽的時候了解過它,會套用模版,但確沒有深入理解這個東西,先學會用輪子,然後再學造輪子嘛,這段時間再回頭研究了一下,發現二進位制在演算法中真的是的好東西,它可以使演算法的時間複雜度降到n的二進位制表示中的1相關,大家都知道,求乙個二進位制中的1的個數,這個時間複雜度為...