輸入乙個數列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 的操作輸出答案。
5123453
q 2 3
c 3 9
q 1 4
516
圖大家自己上網找,這裡解釋樹狀陣列的構造
假如有兩個陣列,其中乙個是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]也加完了,這個是真實存在的現象,然後也會很好記憶,如果還有疑惑可以自己去推其他的
下面給出此題**:
#includeusing namespace std;
int maxn=100010;
int n,m;int a[100010];
int c[100010];
char s[2];
int lowbit(int p)
void add(int p,int num)
return;
}int query(int p)
return tmp;
}int main()
scanf("%d",&m);
for(int i=1;i<=m;i++)
else
}
return 0;
}
樹狀陣列入門(求和)
輸入乙個數列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,所以它的...