一、幾個問題
問題一:已知陣列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 的線段樹,構建結果如下 在區間求和問題上,在葉子節點,顯然劃線部分的值可以由父親節點 左端葉子節點得到。那麼,這部分資訊就是冗餘的,沒有儲存的必要。同理,可以推導出所有冗餘的部分如下 那麼,去除冗餘部分後的結果如下 給每乙個節點乙個編號。我...