因為是樹狀陣列的第一篇,所以可能會略微加一點樹狀陣列的介紹(其實我也不清楚 )。
直接由題目引入,然後分析。
樹狀陣列:
1.單點修改,區間查詢
2.區間修改,單點查詢
3.區間修改,區間查詢
description
給定數列a[1],a[2],…,a[n],你需要依次進行 q個操作,操作有兩類:
1 i x:給定i,x,將a[i]加上x;
2 l r:給定l,r,求 ∑ri=la[i]的值(換言之,求a[l]+a[l+1]+⋯+a[r]的值)
input
第一行包含2個正整數n,q,表示數列長度個數,保證a≤n,q≤106
第二行n個整數a[1],a[2],…,a[n],表示初始數列,保證|a[i]|≤106
接下來q行,每行乙個操作,為下列兩種之一:
1 i x:給定i,x,將a[i]加上x;
2 l r:給定l,r,求 ∑ri=1a[i]的值;
保證1≤l≤r≤n, |x|≤106
output
對於每個 2 l r 操作輸出一行,每行有乙個整數,表示所求的結果。
samples
input
3 21 2 3
1 2 0
2 1 3
output
6hint
對於所有資料,1≤n,q≤106,|a[i]|≤106,1≤l≤r≤n,|x|≤106
它的作用是檢驗這個陣列下內含著多少個數,如下圖,可以得知只有偶數的陣列才含有多個,但實際上與數量有關的是該數化為二進位制後,後面0的數量。#include
using
namespace std;
typedef
long
long ll;
ll n,q,x,w,t,tt;
ll c[
1111111];
ll lowbit(ll x)
void
add(ll x,ll w)
}ll sum
(ll x)
return s;
}int
main()
while
(q--
)return0;
}
例如:4的二進位制是100,那麼他就含有4個數(後面有2個0)(100)(二進位制–>十進位制)。
6的二進位制是110,那麼他就含有2個數(前面只有乙個0)(10)(二進位制–>十進位制)。
7的二進位制是111,那麼他就含有1個數(沒有0)(1)(二進位制–>十進位制)。
……以此類推。
ll lowbit(ll x)
那麼如何靠x&(-x)就能實現得到後面有多少個0的操作呢?
例如乙個8位的6的二進位制原碼是:0000 0110,正數的原碼=補碼=0000 0110
我們也可以知道乙個數負數的補碼是原碼取反+1。
所以 -6的補碼 = 1111 1001 +1 = 1111 1010(計算機內部運算靠補碼)
那麼&如果對應位置都是1則是1
得到最後的補碼是0000 0010也就是–>2
(其實很好想,在第乙個1之前的數都會取反消掉,後面的0全變成1,第乙個1變成0,+1以後,在第乙個1的位置上出現1後面全部都是0) (1000–>(取反)0111–>(+1)1000)。
然後返回這個值就得到了該陣列內所含數的數量。
}兩個位置,x表示要修改的值,w表示要增加的數量。比如要x=3的時候, c[3]的值會修改,然後會加上c[3]含有數的數量到達c[4]再加上c[4]含有數的數量到達c[8]結束,這樣操作,把所有含有這個數(c[3])的陣列全部都加上了w。
由於樹狀陣列的特性,無法直接得到數(為了壓縮,比如上圖的a[4]不能直接得到,需要c[4]-c[3]-c[2])。ll sum
(ll x)
return s;
}
所以由這個函式得到的數其實是字首和。例如c[4]=a[1]+a[2]+a[3]+a[4]。
通過上面的解釋,**就很清楚了,沒有什麼難懂的地方了,因為是字首和所以求區間值得時候按照字首和的公式去求即可(求3-6的和就是 sum(6)-sum(2))。int
main()
while
(q--
)return0;
}
以上只是鄙人的拙見,如果有錯誤、不足之處,還請指正。
樹狀陣列 1 單點修改,區間查詢
這是一道模板題。給定數列 a 1 a 2 a n 你需要依次進行 q 個操作,操作有兩類 1 i x 給定 i,x,將 a i 加上 x 2 l r 給定 l,r,求 ri la i 的值 換言之,求 a l a l 1 a r 的值 第一行包含 2 個正整數 n,q,表示數列長度和詢問個數。保證 ...
樹狀陣列 單點修改區間查詢
樹狀陣列,時間複雜度o mlogn 明顯優於暴力列舉以及字首和,主要用於單點修改區間查詢 當然還有區間修改單點查詢 如果一道題中只有區間查詢,那麼建議使用字首和維護 思想直接理解不好理解,借助資料 a陣列下標12 3456 78數值2 5632 714以上是我們要儲存的a陣列,就是原資料 b陣列下標...
樹狀陣列(單點修改區間查詢)
lowbit是用來取出二進位制中最低位數的1所代表的二進位制的值。只需要記下 就行了 int lowbit int x 將乙個樹的最子節點修改,則其父節點也需要更改,父父節點也需要修改。x x lowbit x 就是用來取出其父節點的。void add int x,int k 能查詢原陣列的字首和,...