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

2021-08-06 04:03:57 字數 1430 閱讀 9080

樹狀陣列之————區間修改+區間查詢

樹狀陣列的工作是 對一組資料進行快速修改查詢操作

最基本的功能是 單點修改+區間查詢。

然後厲害的是 區間修改+單點查詢(用陣列del[i]表示原陣列a[i]-a[i-1]的值)

更厲害的來了。。。

區間修改+區間查詢

用陣列del[i]記錄原陣列a[i]與前一項和,即del[i]=a[i]-a[i-1]

求陣列a的前n項和就是:

s(n) = a[1]+a[2]+...a[n]

= del[1] + (del[1]+del[2]) + .... + (del[1]+del[2]+....del[n])

= n*del[1] + (n-1)*del[2] + .... + 1*del[n]

= (n+1 -1)*del[1] + (n+1 -2)*del[2] + .... + (n+1 -n)*del[n]

= (n+1)*(del[1]+del[2]+ ... +del[n]) - (1*del[1] + 2*del[2] + ... + n*del[n])

= (n+1)*sum(del[i], 1<=i<=n) - sum(i*del[i], 1<=i<=n)

其實只需要求出(n+1)*sum(del[i]) ,和sum(i*del[i], 1<=i<=n),相減即可

所以就用兩個樹狀陣列共同維護

用陣列c1[i]維護del[i]

用陣列c2[i]維護i*del[i]

對陣列進行操作時,用時更新這兩個陣列即可。查詢時,用上面推導的公式

對於那兩個查詢和修改函式不變,依然沿用最老套的模板

**實現詳見例題:1082 線段樹練習 3

【**】:

#include#includeusing namespace std;

typedef long long ll;

ll a[202020];

ll del[202020];

ll c1[202020];//維護del

ll c2[202020];//維護x*del[x]

ll n;

void add(ll *c,ll k,ll num)

ll read(ll *c,ll k)//查詢區間1~k

ll sum(ll k)

int main()

ll q;cin>>q;

while(q--)

else

{ ll a,b;cin>>a>>b;

ll sumr=sum(b);

ll suml=sum(a-1);

cout<

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

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

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

題面 首先,我們要推乙個柿子。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 把最後一位二進位制最低位...