在考試中 因為不清楚二維樹狀陣列怎麼用 而失手了無數遍了...
今天終於把這個坑填了.... =_=
把查詢第\(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在最壞情況下...