先上模板…
單點更新
const
int n =
1003
;int n;
int a[n]
;void
update
(int i,
int d)
intgetsum
(int i)
區間更新const
int n =
1003
;int n;
int a[n]
;void
update
(int i,
int d)
intgetsum
(int i)
void
range_update
(int l,
int r,
int d)
嗯…大概就是樹狀陣列有個啥用處之類的話…
有一類這樣的題目,給你一串數字,其中有很多詢問,問的是某一段上的和是多少。
初始陣列a = ,再有3個詢問。
陣列中1~2的和是多少? 答案:a[1] + a[2] = 1
陣列中2~3的和是多少? 答案:a[2] + a[3] = -1
陣列中3~5的和是多少? 答案:a[3] + a[4] + a[5] = 7
如果是正常的思維,我們可能會直接暴力迴圈去計算出答案,但如果陣列長度很大,詢問很多, 直接迴圈暴力的複雜度就很高。所以這時候就引進了字首和,如果首先先處理出它的字首和,就能o(1)得出答案了。
處理後陣列b = ,再有3個詢問。
陣列中1~2的和是多少? 答案:b[2] - b[0] = 1
陣列中2~3的和是多少? 答案:b[3] - b[1] = -1
陣列中3~5的和是多少? 答案:b[5] - b[2] = 7
所以從這裡就可以發現出,我們可以先處理出陣列某一段區間的和存起來,方便我們以後使用。
現在如果不只是詢問,而是時而詢問時而修改呢,那這樣預處理出來的字首和也有可能是錯的,所以就引入了樹狀陣列,能夠在o(logn)時間內完成詢問和修改。
我剛開始接觸樹狀陣列時跳過了理解它的過程,只學習了要怎麼用,一直不知道為什麼能在logn的時間裡完成n時間的操作。其實就是二進位制,它用到了lowbit這樣的東西。
int
lowbit
(int x)
lowbit的實現的操作就是計算出二進位制中最後一位的1所在位置的值等於多少。
lowbit(1
(001)1_
1(001)
) = 1
(001)1_
1(001)
, lowbit(2
(010)2_
2(010)
) = 2
(010)2_
2(010)
lowbit(3
(011)3_
3(011)
) = 1
(001)1_
1(001)
, lowbit(4
(100)4_
4(100)
) = 4
(100)4_
4(100)
lowbit(5
(101)5_
5(101)
) = 1
(001)1_
1(001)
, lowbit(6
(110)6_
6(110)
) = 2
(010)2_
2(010)
lowbit(7
(111)7_
7(111)
) = 1
(001)1_
1(001)
樹狀陣列處理後的陣列b[i
]=a[
i−lo
wbit
(i)+
1]+a
[i−l
owbi
t(i)
+2]+
...+
a[i]
b[i] = a[i-lowbit(i)+1] + a[i-lowbit(i)+2] + ... + a[i]
b[i]=a
[i−l
owbi
t(i)
+1]+
a[i−
lowb
it(i
)+2]
+...
+a[i
]那麼為什麼要這樣做呢,這樣做有什麼好處呢?
因為在這樣操作了後,b[i]再進行其逆過來加到sum裡,sum能恰好表示出a陣列的字首和,這樣做的好處就是優化了時間複雜度i-lowbit(i)+1~i之間最多就只有logn那麼大。
那麼要怎麼逆操作呢,為什麼sum就恰好能表示出a陣列的字首和呢?
其中,b[1] = a[1],
b[2] = a[1] + a[2],
b[3] = a[3]
b[4] = a[1] + a[2] + a[3] + a[4],
b[5] = a[5],
b[6] = a[5] + a[6],
b[7] = a[7]
如果這時候要求1~7的字首和,對b[7]逆操作加到sum裡。
首先 sum += b[7], 7 -= lowbit(7) -> 6
sum += b[6], 6 -= lowbit(6) -> 4
sum += b[4], 4 -= lowbit(4) -> 0退出
發現這樣的話sum = b[7] + b[6] + b[4],正好能表示出1~7的字首和。
那麼這到底是怎麼回事呢,就是二進位制不斷丟1的過程。
對於7,是從111到110到100…mark!!
深入理解指標 陣列
指標的本質是乙個變數,也需要占用一定的空間一般為四個位元組不論其指向的型別。指標用來儲存記憶體位址的值。通過指標我們能做到不通過變數來改變變數的值。號的意義 在指標宣告時,代表宣告的變數為指標變數。int i 10 int p i 在指標使用時,表示取指標所指向的位址中的值。p 12 另外指標宣告時...
深入理解陣列 下
本文以實踐為主,舉幾個基本的常用的例子。所以原始碼已上傳至github 鏈結 public int find int index 複製 public boolean insert int index,int value for int i count 1 i index i array index ...
深入理解c語言陣列
一 陣列名是什麼 陣列就是一段連續可用的記憶體。比如宣告乙個 int陣列 int array array代表什麼?有的資料說 陣列名是指向陣列首位址的常量指標。下面我們可以驗證一下。我都知道sizeof操作符可以返回乙個物件或者型別所佔的記憶體位元組數。如 int i 1 那麼sizeof i 的結...