樹狀陣列入門(求和)

2022-05-19 11:13:35 字數 1568 閱讀 5556

輸入乙個數列a1,a2….an(1<=n<=100000),在數列上進行m(1<=m<=100000)次操作,操作有以下兩種:

(1)格式為c i x,其中c為字元"c",i和x(1<=i<=n,|x|<=10000)都是整數,表示把把a[i]改為x

(2)格式為q l r,其中q為字元"q",l和r表示詢問區間為[l,r](1<=l<=r<=n),表示詢問a[l]+…+a[r]的值。

第一行輸入n(1<=n<=100000),表述數列的長度,接下來n行,每行乙個整數(絕對值不超過10000)依次輸入每個數

;接下來輸入乙個整數m(1<=m<=100000),表示運算元量,接下來m行,每行為c i x或者q l r。

對於每個q l r 的操作輸出答案。

512

3453

q 2 3

c 3 9

q 1 4

5

16

圖大家自己上網找,這裡解釋樹狀陣列的構造

假如有兩個陣列,其中乙個是a陣列,另乙個是樹狀陣列t陣列

樹狀陣列類似字首和,但是效率要高得多

t[1]=a[1],t[2]=t[1]+a[2],t[3]=a[3],t[4]=t[2]+t[3],t[5]=a[5],t[6]=t[2]+a[6],t[7]=a[7],t[8]=t[7]+t[6]+t[4];

然後大家可以發現乙個規律,樹狀陣列t字尾為奇數就是陣列a中的本身,轉成二進位制後就很直觀了

就拿8舉個例子,8轉成二進位制後是1000

k代表的是轉成二進位制之後的出現0的位置,二進位制最右一位是2^0,那麼我們可以發現(n=8)n-2^k恰好就是t陣列加上的

就像8二進位制第乙個出現0的位置是第0個,那麼n-2^0=8-1=7,t[8]確實加了t[7]。

這是不是偶然呢?顯然是不可能的,不信我們繼續看,8二進位制第二個0出現在第1個位置,那麼n-2^1=8-2=6,t[8]也確實加了t[6],這樣一來n-2^2=8-4=4,0走完了,t[8]也加完了,這個是真實存在的現象,然後也會很好記憶,如果還有疑惑可以自己去推其他的

下面給出此題**:

1 #include2

using

namespace

std;

3int maxn=100010;4

int n,m;int a[100010];5

int c[100010];6

char s[2];7

int lowbit(intp)8

11void add(int p,int

num)

1218

return;19

}20int query(int

p)21

28return

tmp;29}

30int

main()

31

38 scanf("

%d",&m);

39for(int i=1;i<=m;i++)

4049

else

50

56}

57return0;

58 }

樹狀陣列入門(求和)

輸入乙個數列a1,a2 an 1 n 100000 在數列上進行m 1 m 100000 次操作,操作有以下兩種 1 格式為c i x,其中c為字元 c i和x 1 i n,x 10000 都是整數,表示把把a i 改為x 2 格式為q l r,其中q為字元 q l和r表示詢問區間為 l,r 1 l...

樹狀陣列 區間求和

樹狀陣列 是乙個查詢和修改複雜度都為log n 的資料結構,假設陣列a 1.n 那麼查詢a 1 a n 的時間是 log n 級別的。所以如果要解決 陣列中的元素不斷被修改,怎麼才能快速地獲取陣列中連續m個數的和 這個問題的話,用樹狀陣列就再好不過了 首先,什麼是樹狀陣列呢?樹狀陣列就是用另外乙個陣...

樹狀陣列1 樹狀陣列入門

仔細看一下,發現tree的每乙個節點的高度並不是隨意的,而是由它轉成二進位制之後末尾連續零的數量決定的,連續零的數量加1,就是高度,例如 3 11 零的數量為0,加1等於1,所以它的高度就是1 6 110 零的數量為1,加1等於2,所以它的高度就是2 8 1000 零的數量為3,加1等於4,所以它的...