poj 3468 樹狀數組解法(解決區間更新,區間求和)

題意:給你一個數列,每次詢問一個區間的和,或者每次將一個區間的所有元素都加上一個數

一 算法    

    樹狀數組天生用來動態維護數組前綴和,其特點是每次更新一個元素的值,查詢只能查數組的前綴和,

但這個題目求的是某一區間的數組和,而且要支持批量更新某一區間內元素的值,怎麼辦呢?實際上,

還是可以把問題轉化爲求數組的前綴和。

 

    首先,看更新操作update(s, t, d)把區間A[s]...A[t]都增加d,我們引入一個數組delta[i],表示

A[i]...A[n]的共同增量,n是數組的大小。那麼update操作可以轉化爲:

1)令delta[s] = delta[s] + d,表示將A[s]...A[n]同時增加d,但這樣A[t+1]...A[n]就多加了d,所以

2)再令delta[t+1] = delta[t+1] - d,表示將A[t+1]...A[n]同時減d

 

    然後來看查詢操作query(s, t),求A[s]...A[t]的區間和,轉化爲求前綴和,設sum[i] = A[1]+...+A[i],則

                            A[s]+...+A[t] = sum[t] - sum[s-1],

那麼前綴和sum[x]又如何求呢?它由兩部分組成,一是數組的原始和,二是該區間內的累計增量和, 把數組A的原始

值保存在數組org中,並且delta[i]對sum[x]的貢獻值爲delta[i]*(x+1-i),那麼

                            sum[x] = org[1]+...+org[x] + delta[1]*x + delta[2]*(x-1) + delta[3]*(x-2)+...+delta[x]*1

                                         = org[1]+...+org[x] + segma(delta[i]*(x+1-i))

                                         = segma(org[i]) + (x+1)*segma(delta[i]) - segma(delta[i]*i),1 <= i <= x

=segma(org[i]-delta[i]*i)+(x+1)*delta[i],  i<=1<=x   //by huicpc0207 修改  這裏就可以轉化爲兩個個數組

這其實就是三個數組org[i], delta[i]和delta[i]*i的前綴和,org[i]的前綴和保持不變,事先就可以求出來,delta[i]和

delta[i]*i的前綴和是不斷變化的,可以用兩個樹狀數組來維護。

 

    樹狀數組的解法比樸素線段樹快很多,如果把long long變量改成__int64,然後用C提交的話,可以達到1047ms,

排在22名,但很奇怪,如果用long long變量,用gcc提交的話就要慢很多。

發佈了18 篇原創文章 · 獲贊 12 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章