樹狀陣列 區間修改,區間查詢

2022-02-27 05:19:02 字數 1277 閱讀 6922

也許更好的閱讀體驗

好東西,以後可以不打線段樹了

本篇假定讀者都會最基礎的兩種樹狀陣列,即區改單查和單改區查

思考如何維護乙個區間的值,想到了差分

對乙個差分陣列做一次字首和可以得到每個位置的值

再對每個位置累加一下就是乙個區間的值

公式化的講,就是

設差分陣列為\(c\)

則每個位置的值

\(val_i=\sum\limits_^ic_j\)

乙個區間\([l,r]\)的值

\(s_=\sum\limits_^rval_i\)

寫成字首和相減的形式就是

\(s_=\sum\limits_^rval_i-\sum\limits_^val_i\)

不難發現,乙個區間的值實際上就是差分陣列字首和的字首和做減法

也就是說,我們只要維護出字首和的字首和就可以用樹狀陣列維護區間了

考慮如何維護字首和的字首和

\(s_p=\sum\limits_^p\sum\limits_^ic_j\)

考慮每個\(c_j\)的出現次數,可以得到

\(s_p=\sum\limits_^p\left(p-i+1\right)c_i=\left(p+1\right)\sum\limits_^pc_i-\sum\limits_^pi *c_i\)

經過如上的簡單推導,我們只要維護\(\sum\limits_^pc_i\)和\(\sum\limits_^pi *c_i\)這兩個東西就可以了

前者就是差分陣列,而後者我們只要在維護差分陣列時乘以相應的位置的下標即可

這兩個東西我們都可以用樹狀陣列維護單點修改區間查詢一樣的方法維護

int c1[maxn],c2[maxn];

int lbt (int x)

void modify (int l,int r,int v)//維護差分陣列

最開始這兩句我沒有看懂,不是說好的維護\(i*c_i\)嗎,怎麼寫出來時就變成\(l*v\)和\(r*v\)了

如果你也有這樣的疑惑,這說明太久沒打樹狀陣列或者沒想樹狀陣列的原理你也忘記樹狀陣列的原理了

這個東西維護的是差分陣列,而不是差分陣列的字首和!

對於查詢

int query (int l,int r)

如有**講得不是很明白或是有錯誤,歡迎指正

如您喜歡的話不妨點個贊收藏一下吧

樹狀陣列區間修改區間查詢

題面 首先,我們要推乙個柿子。displaystyle sum a i 把a i 用差分陣列表示出來,就可以寫成 displaystyle sum sum d i 我們考慮一下,每個d i 出現的次數是一定的。那我們可以換一下列舉順序,先列舉d i 在列舉他出現的次數,就可以變成 displayst...

樹狀陣列高階 區間修改 區間查詢

區間修改與區間查詢 今天老糊塗了,樹狀陣列忘記了,基本的只要單點修改 區間查詢功能,如果要進行區間加操作,需要把樹狀陣列進行改造。我們首先來回顧樹狀陣列的功能 lowbit x x 返回二進位制最低位 1的值 比如 x 1010 那麼lowbit值為2 x lowbit x 把最後一位二進位制最低位...

樹狀陣列的應用(區間修改 區間查詢)

樹狀陣列之 區間修改 區間查詢 樹狀陣列的工作是 對一組資料進行快速修改查詢操作 最基本的功能是 單點修改 區間查詢。然後厲害的是 區間修改 單點查詢 用陣列del i 表示原陣列a i a i 1 的值 更厲害的來了。區間修改 區間查詢 用陣列del i 記錄原陣列a i 與前一項和,即del i...