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

2021-08-09 23:41:29 字數 1441 閱讀 8505

今天,我們再在樹狀陣列上進一步突破,我們來講一講區間修改和區間查詢。同樣的,這需要各位對樹狀陣列的基本知識有所了解,大家可以看看我的另一篇文章:樹狀陣列趣解。

下面進入正題。

同樣的,我還是先給**,再講解。其實,我個人比較喜歡直接看**,有時,看別人的解釋,反而看得稀里糊塗,不如先看看**,自己會有自己的理解,然後再看解釋就不會暈了。(也有可能是某些作者說得太簡略了)

有些是以前的**,但由於會用到,這裡可能會再寫一遍。

int lowbit(int x)
void add(int *c,int x,int p)

}

int

sum(int *c,int x)

return ans;

}

int truesum(int x)
int query(int l,int r)
void change(int l,int r,int p)
在這些**中,有些變數可能出現的比較突兀,我會在解釋中說的。

好,下面是cgg解密時刻!

首先,我先講一下總體的思路。

我們設a是原陣列。

接下來我們需要引出乙個概念:差分陣列。你可能聽過,也可能沒聽過,這都無所謂,我簡單介紹一下:

我們設差分陣列是c,那麼有如下定義:

c[1]=a[1]

c[i]=a[i]-a[i-1]

很好理解吧!

那麼我們下面要做乙個公式推導。

sum(1,n)

=a[1]+a[2]+a[3]+…+a[n-1]+a[n]

=c[1]+(c[1]+c[2])+…+(c[1]+c[2]+…+c[n])

=n(c[1]+c[2]+…+c[n])-(0c[1]+1c[2]+2c[3]+…+(n-1)c[n]).

這裡sum表示前n項之和。

那麼我們有什麼發現?

我們可以設定兩個樹狀陣列,乙個是c1表示差分陣列,另乙個c2則是c2[i]=(i-1)*c1[i]。這樣的話,我們就可以區間查詢了。

那麼我們又是怎麼實現區間修改的呢?

其實也很簡單,我們看一下change()函式,有什麼發現?

我們會發現,它對於兩個陣列,每個只改了頭尾兩個值,為什麼?

這就要回到我們的定義,我們的兩個樹狀陣列均可以算的上是差分陣列(c2也有差分的意味),所以,試想一下,如果我們對區間[l,r]上的每個數都加上p,那麼c1[l+1]到c1[r]會發生變化嗎?不會!因為區間內的每個數都加了p,所以他們之間的差是不變的,所以我們只需要改變兩頭的差值即可,這樣就是實現了區間修改。

再稍微辨析一下3和4兩段**,兩個都是前幾項和,但3求的是樹狀陣列前幾項和,而4才是原陣列的前幾項和,也是我們要求的。

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

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

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

單點更新,區間查詢 我們知道,樹狀陣列最基本的功能是 單點更新,區間查詢 如下 int lowbit int x void add int x,int val int ask int x return res 區間更新,單點查詢 通過 單點更新,區間查詢 功能 差分的思想,我們實現了 區間更新,單點...

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

也許更好的閱讀體驗 好東西,以後可以不打線段樹了 本篇假定讀者都會最基礎的兩種樹狀陣列,即區改單查和單改區查 思考如何維護乙個區間的值,想到了差分 對乙個差分陣列做一次字首和可以得到每個位置的值 再對每個位置累加一下就是乙個區間的值 公式化的講,就是 設差分陣列為 c 則每個位置的值 val i s...