一些懶人由於覺得線段樹難寫的一逼,於是發明了樹狀陣列。於是大佬們拿它去卡常。啥樹套樹的你套個樹狀陣列,常數就小了下來,就快了好幾倍。苦逼寫線段樹的同學還過不去了。
所以本著不卡別人也不被別人卡的思想,我們來學習一波樹狀陣列。首先樹狀陣列比線段樹優秀的一點就是它的空間就小一半。我們只用開乙個大小為n的陣列,存的樣子大概像這樣:
什麼意思呢?看到這個樹形結構了麼?
不好說明,舉個例子:2號點存1-2的和;8號點存1-8的和;10號點存9-10的和;13號點存13-13的和;5號點存5-5的和。
然後我們就可以做到(單點修改,區間求和)
我們來看一道題:p3374 【模板】樹狀陣列 1
我們再引入乙個概念:lo
wbit
(x)=
x low
bit(
x)=x
的2的最大次冪。舉個例子:lo
wbit
(6)=
2(6=
2∗3)
;low
bit(
12)=4
(12=4
∗3) low
bit(
6)=2
(6=2
∗3);
lowb
it(12
)=4(
12=4∗
3)。然後我們就可以lo
gnl og
n求字首和了,查詢時每次−l
owbi
t(x)
− lo
wbit
(x),然後把那乙個位置裡的和加入an
s ans
裡。再舉個例子,求7的字首和:7—
—6(7
−low
bit(
7))—
—4(6
−low
bit(
6))—
—0(4
−low
bit(
4)) 7——
6(7−
lowb
it(7
))——
4(6−
lowb
it(6
))——
0(4−
lowb
it(4
))到0就結束。
從圖里可以發現,我們正好把每個7前面的數都加了一遍。原理就是lo
wbit
(x) low
bit(
x)其實表示
x x
的管理範圍。
然後考慮修改:修改時每次+l
owbi
t(x)
' role="presentation" style="position: relative;">+lo
wbit
(x)+
lowb
it(x
),然後修改那一位置的值,我們就可以把所有實際管理
x x
的格仔修改掉了。可以自己手動模擬一下,我就不舉例子了。
然後字首和相減,我們很容易可以過這道題。
接著我們在來看一道題:p3368 【模板】樹狀陣列 2
誒,這道題要求我們(區間修改,單點查詢)。
看似剛剛那種方法已經無解了,顯然無法區間修改,我們每一次單點修改複雜度就是lo
gn' role="presentation" style="position: relative;">log
nlog
n的,要是一段區間的話豈不是coldcold。那我們要想個辦法把區間修改變為單點修改。於是很容易會想到差分。然後我們很驚奇地發現查詢操作也很簡單了。考慮我們以前差分後統計答案的方法,其實就是這個點前面的字首和。這不是可以用樹狀陣列輕鬆解決麼?
舉個例子:[3,6] +2,3號點+2,7號點-2。
查詢4號點,求四號點字首和。
用我們剛剛那種方法維護陣列即可。
我們樹狀陣列就講完了,是不是很簡單呢,時間上吊打線段樹。
誒,不對啊,你還沒講lo
wbit
l ow
bit怎麼求。
啪!!!
哦~其實你可以腦補出一種方法,據說考場上各路大佬現推公式都可以求。只要時間控制在o(
1)o (1
)即可。這裡提供一種簡單方法:
lowbit(x)=(-x)&x;
樹狀陣列1 樹狀陣列入門
仔細看一下,發現tree的每乙個節點的高度並不是隨意的,而是由它轉成二進位制之後末尾連續零的數量決定的,連續零的數量加1,就是高度,例如 3 11 零的數量為0,加1等於1,所以它的高度就是1 6 110 零的數量為1,加1等於2,所以它的高度就是2 8 1000 零的數量為3,加1等於4,所以它的...
樹狀陣列 瞎bb 樹狀陣列
樹狀陣列是乙個利用一維陣列和位運算組成的求解區間問題的高效資料結構,其構造如圖所示 首先,我們要用它解決單點修改 區間查詢的操作。根據這張圖我們建立乙個陣列bit,下標就是圖中顯示的十進位制數。bit i 就表示了圖中所示的一段區間的和,例如bit 6 sum 5,6 bit 4 sum 1,4 下...
樹狀陣列 二維樹狀陣列模板
樹狀陣列模板 int lowbit int x int add int x,int val int que int x 模板題 題解 include include include using namespace std int c 300000 rank 300000 int n int lowb...