「高階」資料結構 樹狀陣列!

2022-08-31 15:15:15 字數 2210 閱讀 7085

** 

最簡單的樹狀陣列就是這樣的:

void add(int p, int x)

int ask(int p)

int range_ask(int l, int r)

通過「差分」(就是記錄陣列中每個元素與前乙個元素的差),可以把這個問題轉化為問題1。

設原陣列為a[i], 設陣列d[i]=a[i]−a[i−1](a[0]=0),則 a[i]=∑ij=1d[j],可以通過求d[i]的字首和查詢。

當給區間[l,r]加上x的時候,a[l] 與前乙個元素 a[l−1] 的差增加了x,a[r+1] 與 a[r] 的差減少了x。根據d[i]陣列的定義,只需給a[l] 加上 x, 給a[r+1] 減去 x即可。

void add(int p, int x)

void range_add(int l, int r, int x)

int ask(int p)

這是最常用的部分,也是用線段樹寫著最麻煩的部分——但是現在我們有了樹狀陣列!

怎麼求呢?我們基於問題2的「差分」思路,考慮一下如何在問題2構建的樹狀陣列中求字首和:

位置p的字首和 =∑i=1pa[i]=∑i=1p∑j=1id[j]在等式最右側的式子∑pi=1∑ij=1d[j]中,d[1] 被用了p次,d[2]被用了p−1

次……那麼我們可以寫出:位置p的字首和 =∑i=1p∑j=1id[j]=∑i=1pd[i]∗(p−i+1)=(p+1)∗∑i=1pd[i]−∑i=1pd[i]∗i

那麼我們可以維護兩個陣列的字首和:乙個陣列是 sum1[i]=d[i],另乙個陣列是 sum2[i]=d[i]∗i。

位置p的字首和即: (p + 1) * sum1陣列中p的字首和 - sum2陣列中p的字首和。

區間[l, r]的和即:位置r的字首和 - 位置l的字首和。

對於sum1陣列的修改同問題2中對d陣列的修改。

對於sum2陣列的修改也類似,我們給 sum2[l] 加上 l * x,給 sum2[r + 1] 減去 (r + 1) * x。

void add(ll p, ll x)

void range_add(ll l, ll r, ll x)

ll ask(ll p)

ll range_ask(ll l, ll r)

用這個做區間修改區間求和的題,無論是時間上還是空間上都比帶lazy標記的線段樹要優。

**另乙個大佬

#include#include#include#includeusing namespace std;

int n,m;

int c[500005];

int lowbit(int x)

void add(int pos,int x)

}void input()

}int query(int pos)

return res;

}int main()

void add(int pos,int x)

}int query(int pos)

return res;

} int main()

int opt,k;

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

else if(opt==2)

}return 0;

}

此處簡略地說明一下原陣列a,差分陣列d 則有an=∑i=1ndi所以∑i=1nai=∑i=1n∑j=1idj=∑i=1n(n−i+1)×di=(n+1)×∑i=1ndi−∑i=1ndi×i

於是我們維護兩個樹狀陣列,c1儲存di,c2儲存di×i

#include#include#includeusing namespace std;

long long c[200005][2];

int n,q;

int lowbit(int x)

void add(int pos,int x,int f)

}long long query(int pos,int f)

return res;

}long long ask(int pos)

int main()

scanf("%d",&q);

for(int i=1;i<=q;i++)

else if(opt==2)

}return 0;

}

資料結構 樹狀陣列

區間資訊的維護與查詢專題 樹狀陣列 1.問題 動態連續和查詢問題。給定乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構,支援以下兩種操作。add x,d 操作 讓ax增加d.query l,r 計算al al 1 ar.對普通陣列進行 一次修改或 特定區間 求和,時間複雜度為o n n...

資料結構 樹狀陣列

原陣列 字首和 範圍和 原陣列更改陣列元素在求和效率較低,引入樹狀陣列 假設原陣列a 樹狀陣列c 樹狀陣列 的三種操作 1.lowbit 子葉數 二進位制最低位的1代表多少 實現 int lowbit int n 求 lowbit x returnx x 2.update a i k 假設a i 是...

資料結構 樹狀陣列

講到了線段樹,那就順便講講樹狀陣列吧。假設乙個長度為 12 的線段樹,構建結果如下 在區間求和問題上,在葉子節點,顯然劃線部分的值可以由父親節點 左端葉子節點得到。那麼,這部分資訊就是冗餘的,沒有儲存的必要。同理,可以推導出所有冗餘的部分如下 那麼,去除冗餘部分後的結果如下 給每乙個節點乙個編號。我...