樹狀陣列使用總結

2022-04-29 19:54:10 字數 1311 閱讀 6324

在考試中 因為不清楚二維樹狀陣列怎麼用 而失手了無數遍了...

今天終於把這個坑填了.... =_=

把查詢第\(x\)個位置的值\(s_x\)變為查詢字首和\(s_x = \sum_^x d(i)\)。

其中 \(d(x) = s_x - s_\)。

修改\([l,r]\)的時侯,只需要修改 \(l\) 與 \(r\)+\(1\) 兩個點。

查詢\([1,x]\),則有:

\[res = \sum_^x s_x = \sum_^x \sum_^i d(j)

\]\[\sum_^x \sum_^i d(j) = \sum_^x d(j)(x - j + 1) = (x+1)\sum_^x d(j) - \sum_^x d(j)j

\]所以用兩個樹狀陣列分別維護\(\sum d(i)\)與\(\sum d(i)*i\)即可。

直接維護\((1,1)\)到\((x,y)\)的這個矩陣的和即可。 **類似一維處理即可:

for( x ; x <= n ; x += lowbit(x) )

for( y ; y <= m ; y += lowbit(y) )updata or query

查詢時用一下二維字首和容斥一下就行了。

一樣的轉為差分值:\(s_} = \sum_^x \sum_^y d(i,j)\)

其中$d(i,j) = s_} - s_} - s_} + s_} \(

修改時只修改\)(x_1,y_1)\(、\)(x_1,y_2+1)\(、\)(x_2+1,y_1)\(、\)(x_2+1,y_2+1)$

查詢時一樣的用 單點修改+區間查詢(二維) 的方法查詢。

\[res = \sum_^x \sum_^y \sum_^i \sum_^j d(k,h)

\]把後面兩個\(\sum\)提到前面來:

\[res = \sum_^x \sum_^y d(i,j)(x-i+1)(y-j+1)

\]展開後得到:

$res = res $

$+(x+1)(y+1)\ [\ \sum_^x \sum_^y d(i,j)\ ] \(

\)- (x+1)\ [\ \sum_^x \sum_^y d(i,j)j\ ]\(

\)- (y+1)*\ [\ \sum_^x \sum_^y d(i,j)i\ ]\(

\)+ [\ \sum_^x \sum_^y d(i,j)ij\ ]\(

所以用四個樹狀陣列分別維護\)\sum d()$ , \(\sum d()i\) , \(\sum d()j\) , \(\sum d()ij\) 即可 , 具體實現戳這裡。

樹狀陣列使用總結

有關積分的表述只是我自己的理解,不喜勿噴。一次積分需要dalta有點思考,而二次積分對dalta思考就有點麻煩了。這個方式很直接,題目讓求什麼你就維護什麼 適用於 要改變單項而結果只是對單項積分的題目。滑動視窗 例如 坐火車 大致的題意是給乙個n個數,求第i個數在陣列中左右兩邊相同數值的配對數之和且...

樹狀陣列總結

樹狀陣列的基本知識已經被各種大牛和菜鳥講到爛了,我就不多說了,下面給出基本操作的 假定原陣列為a 1.n 樹狀陣列b 1.n 考慮靈活性的需要,使用int a傳陣列。define lowbit x x x int sum int a,int x void update int a,int x,int...

樹狀陣列總結

樹狀陣列是對乙個陣列改變某個元素和求和比較實用的資料結構。兩中操作都是o logn 在解題過程中,我們有時需要維護乙個陣列的字首和s i a 1 a 2 a i 但是不難發現,如果我們修改了任意乙個a i s i s i 1 s n 都會發生變化。可以說,每次修改a i 後,調整字首和s在最壞情況下...