資料結構 樹狀陣列 子區間的和

2021-07-27 22:37:51 字數 1354 閱讀 9673

一、幾個問題

問題一:已知陣列a,元素個數為n,現在要求a陣列中i到j區間內的和(1<=i<=j<=n)

解法1:每次查詢就把i到j之間每個元素都加起來。最壞情況o(qn)(q為查詢次數)

解法2:用字首和陣列sum[k]來記錄1到k的和,查詢時,就輸出sum[j]-sum[i-1]。o(1)

問題二:已知陣列a,元素個數為n,現在有兩種操作

1、求a陣列中i到j區間內的和(1<=i<=j<=n)

2、將a陣列中a[k]

(1<=k<=n)的值加上d。

解法1:每次查詢就把i到j之間每個元素都加起來,每次更改就把a[k]加上d。

最壞情況o(qn)

解法2:用字首和陣列sum[k]來記錄1到k的和,查詢時,就輸出sum[j]-sum[i-1],更改時,就把k到n之間的所有元素都加上d。最壞情況o(qn)

解法3:樹狀陣列。o(qlog(n))

樹狀陣列就是在這種背景下產生的。

二、樹狀陣列的概念

利用二進位制來分類,每乙個數存的資料是存的乙個區間,它存的區間大小,取決於它的二進位制裡

權值最低的1權值,

如果感覺聽不懂,就來看一下例子吧。

比如說6,轉化成二進位制位110,權值最低的1就是紅色標註的那個1,它的權值是2。

再比如說12,轉化成二進位制位1100

,權值最低的權值就是4。

求它的最低權值有乙個簡便演算法:

接下來就是求和的操作,我們發現1~14之間的和是

a[14]

+a[12]+

a[8],恰好是14對應二進位制a[1110

],a[1100],a[1000]

(以上的1110、1100、1000位二進位制),於是可以發現求和演算法:

int getsum(int x) }

然後是修改操作,實際上就是找它的父親,直到它的父親大於n為止。

void update(int x,int d) }

有了這三個函式,求解上面的問題就容易多了,但是要注意初始化:

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

完整**:

#includeint treearray[1000002],n;

int lowbit(int x)

int getsum(int x)

return sum;

}void update(int i,int x)

}int main()

if(x==1)}}

資料結構 樹狀陣列

區間資訊的維護與查詢專題 樹狀陣列 1.問題 動態連續和查詢問題。給定乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構,支援以下兩種操作。add x,d 操作 讓ax增加d.query l,r 計算al al 1 ar.對普通陣列進行 一次修改或 特定區間 求和,時間複雜度為o n n...

資料結構 樹狀陣列

原陣列 字首和 範圍和 原陣列更改陣列元素在求和效率較低,引入樹狀陣列 假設原陣列a 樹狀陣列c 樹狀陣列 的三種操作 1.lowbit 子葉數 二進位制最低位的1代表多少 實現 int lowbit int n 求 lowbit x returnx x 2.update a i k 假設a i 是...

資料結構 樹狀陣列

講到了線段樹,那就順便講講樹狀陣列吧。假設乙個長度為 12 的線段樹,構建結果如下 在區間求和問題上,在葉子節點,顯然劃線部分的值可以由父親節點 左端葉子節點得到。那麼,這部分資訊就是冗餘的,沒有儲存的必要。同理,可以推導出所有冗餘的部分如下 那麼,去除冗餘部分後的結果如下 給每乙個節點乙個編號。我...