練習 1 樹狀陣列 模板一(單點修改,區間查詢)

2021-10-18 10:49:19 字數 2586 閱讀 5982

因為是樹狀陣列的第一篇,所以可能會略微加一點樹狀陣列的介紹(其實我也不清楚 )。

直接由題目引入,然後分析。

樹狀陣列:

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

#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;

}

它的作用是檢驗這個陣列下內含著多少個數,如下圖,可以得知只有偶數的陣列才含有多個,但實際上與數量有關的是該數化為二進位制後,後面0的數量

例如: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。

ll sum

(ll x)

return s;

}

由於樹狀陣列的特性,無法直接得到數(為了壓縮,比如上圖的a[4]不能直接得到,需要c[4]-c[3]-c[2])。

所以由這個函式得到的數其實是字首和。例如c[4]=a[1]+a[2]+a[3]+a[4]。

int

main()

while

(q--

)return0;

}

通過上面的解釋,**就很清楚了,沒有什麼難懂的地方了,因為是字首和所以求區間值得時候按照字首和的公式去求即可(求3-6的和就是 sum(6)-sum(2))。

以上只是鄙人的拙見,如果有錯誤、不足之處,還請指正。

樹狀陣列 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 能查詢原陣列的字首和,...