2017 8 18訓練日記(樹狀陣列簡述)

2021-08-07 03:16:01 字數 1385 閱讀 2810

今天也就重點看了下樹狀陣列,下面來記一些基礎知識以及和線段樹的對比

主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值;

經過簡單修改可以在log(n)的複雜度下進行範圍修改,但是這時只能查詢其中乙個元素的值(如果加入多個輔助陣列則可以實現區間修改與區間查詢)。

能用樹狀陣列解決的問題,基本上都能用線段樹解決,而線段樹能解決的樹狀陣列不一定能解決。相比較而言,樹狀陣列效率要高很多。

令這棵樹的結點編號為c1,c2...cn。令每個結點的值為這棵樹的值的總和,那麼容易發現:

c1 = a1

c2 = a1 + a2

c3 = a3

c4 = a1 + a2 + a3 + a4

c5 = a5

c6 = a5 + a6

c7 = a7

c8 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8

...c16 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16

為什麼呢!!!!

很容易知道c8表示a1~a8的和,但是c6卻是表示a5~a6的和,為什麼會產生這樣的區別的呢?或者說發明她的人為什麼這樣區別對待呢?

答案是,這樣會使操作更簡單!看到這相信有些人就有些感覺了,為什麼複雜度被log了呢?可以看到,c8可以看作a1~a8的左半邊和+右半邊和,而其中左半邊和是確定的c4,右半邊其實也是同樣的規則把a5~a8一分為二……繼續下去都是一分為二直到不能分樹狀陣列巧妙地利用了二分,樹狀陣列並不神秘,關鍵是巧妙!

樹狀陣列的基礎就是乙個被構造出來的式子:c[i]=a[i]+a[i-1]+....+a[i-2^k+1];k代表i的二進位制的最後連續0的個數 比如 對於1000和101000,k=3。

用c++來實現樹狀陣列

#include

using namespace std;

int n,m,i,num[100001],t[200001],l,r;//num:原陣列;t:樹狀陣列 

int lowbit(int x)

void change(int x,int p)//將第x個數加p 

return;

}int sum(int k)//前k個數的和 

return ans;

}int ask(int l,int r)//求l-r區間和 

int main()

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

{cin>>l>>r;

cout/

//明天繼續樹狀陣列,再看些例題估計就能應用了

訓練日記 20161024

初賽好像不會掛了,好開心!版權原因,不上傳題目。題意 求1 n n 1000 的排列中逆序對恰好為 k 個的排列數目。多測。題解 f i j 表示前 i 個數,逆序對個數恰好為 j的排列個數,易得轉移方程f i j i 1k 0f i 1 j k 用字首和優化可使複雜度降為o n2 題意 對於乙個長...

訓練日記 20170324

長久不更新部落格了。期間經歷了恰好被ag線踩的wc,經歷了漫長痛苦的小高考準備。現在終於可以重整旗鼓,向省選進發!幾個月來,唯一不變的是我仍然是個超級蒟蒻 版權原因,不上傳題目。題意 最小樹形圖 去年就接觸 聽說 過的演算法,一直沒有真正寫過。因為各種奇怪的細節錯誤,調了好幾個小時 比如找環時沒有判...

訓練日記 20170328

今天的題目似乎很水 好多人都提前ak離場了,於是提前一小時收題。但是我還是各種不會。思維江化?話說,聽到一句很有趣的話 山不在高,有林則徐 水不在深,有江 題意 給定一棵有n n 105 個節點的有根樹,編號互不重複。詢問有多少棵子樹內節點編號構成乙個連續區間。題解 水題,對於每個節點 i 記錄以該...