樹狀陣列複習筆記

2022-05-05 16:48:08 字數 2069 閱讀 3032

樹狀陣列,字首和,差分

首先我們要明白樹狀陣列維護的是字首和,這也是普通樹狀陣列只能區間修改單點查詢或者單點修改區間查詢的原因。

其實樹狀陣列也是可以支援區間修改區間查詢的。

我們設陣列 \(t\) 為陣列 \(a\) 的差分陣列,那麼顯然差分陣列的字首和陣列就是原陣列 \(a\),設陣列 \(sum\) 為 \(a\) 的字首和陣列。

那麼就有

\[a_1=t_1,a_2=t_1+t_2,a_3=t_1+t_2+t_3,a_r=t_1+t_2+...+t_r

\]\[sum_1=a_1,sum_2=a_1+a_2,sum_3=a_1+a_2+a_3,sum_r=a_1+a_2+a_3+...+a_r

\]將 \(t\) 代入 \(sum\) 得

\[sum_1=t_1,sum_2=t_1+t_1+t_2,sum_3=t_1+t_1+t_2+t_1+t_2+t_3,sum_r=t_1*r+t_2*(r-1)...t_r*1

\]其實\(sum_r=t_i*(r-i+1)\)

\((1\le i \le r)\)

在下面為了方便,我們直接用數學符號 \(\sum_^\) 表示從 \(j\) 到 \(n\) 所有 \(a_i\) 的和。

所以\[sum_r=\sum_^t_i*(r-i+1)

\]\[sum_r=\sum_^t_i*(r-(i-1))

\]因為這種形式不太好維護,所以我們就可以將裡面的裡面的式子拆開

\[sum_r=\sum_^t_i*r-\sum_^t_i*(i-1)

\]然後就可以發現這兩個東西都可以用樹狀陣列來維護,所以我們需要維護兩個樹狀陣列乙個是 \(\sum_^t_i\) 另乙個是 \(\sum_^t_i*(i-1)\) 。

那麼第乙個樹狀陣列修改就和原來的一樣,第二個陣列修改需要改為將增加的數乘上 \(pos-1\) 。

p3372 【模板】線段樹 1

\(code\)

#include#define ll long long

#define pii pair#define mp make_pair

#define one first

#define two second

using namespace std;

const int n=2e5+100;

int n,m;

pii t[n];

int a[n];

inline pii operator +(pii a,pii b)

inline int lowbit(int x)

inline void update(int pos,ll k)

inline ll query(int pos)

int main()

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

else

}return 0;

}

我們發現正常樹狀陣列維護的是字首和,其實樹狀陣列可以維護字首和是因為字首和滿足結合律,因為區間最值不滿足結合律樹狀陣列不能維護區間最值。雖然可以比線段樹多乙個 \(\log\),但是為什麼不寫線段樹呢。

其實如果不帶修的話,直接陣列就可以維護就可以維護字首最值。

但其實樹狀陣列維護字首最值大值的時候只能將乙個數修改為比它大的數,因為樹狀陣列不像線段樹一樣是真的把值進行修改,樹狀陣列只是修改的字首。所以當乙個數要加乙個數的時候,只能在原陣列裡先找到這個數,然後加完時候直接修改為新數。

其實維護字首最小也是只能維護修改為比原數小的數。

至於維護字尾最值,只需要將陣列的下標翻轉一下就可以了,其實就是用最大的下標 \(+1\) 減去當前下標。

樹狀陣列最基礎的操作是單點修改查詢字首,這個操作你會發現和權值線段樹很像,而且在對值域建樹狀陣列之後,你會發現現在對於乙個數的字首和其實就是小於等於當前數的個數,也就是這個數的排名。我們也可以通過翻轉值域,其實就是用值域 \(\max+1\) 減去當前的數,來實現維護大於等於當前數的個數的數。

當然可以和維護字首最值結合起來,用來優化 \(dp\) 。值域怎樣維護比當前值大的值的字尾,我們還需要翻轉值域。

至於怎樣維護第 \(k\) 大,我們可以用倍增樹狀陣列來實現。

先咕著...

演算法複習之 樹狀陣列

早就想著把以前搞acm的演算法複習一遍,那可是瑰寶啊,一直沒時間,之前面實習就有此感慨,以前學的演算法都忘了,明日要去面個不知名的公司,準備下吧,先把樹狀陣列和trie圖複習下,明天湊合應對。不多說,上問題 給你乙個陣列a n 假設存int數,對這個陣列的操作有2種 1 修改陣列中某元素的值 2 查...

筆記 樹狀陣列

主要看圖 i往上找就是i 2 k 往下就是減 k是i的二進位制右邊0的個數 2 k 直接等於i i 傳送門 寫的很好 總結 首先,明白樹狀陣列所白了是按照二分對陣列進行分組 維護和查詢都是o lgn 的複雜度,複雜度取決於最壞的情況,也是o lgn lowbit這裡只是乙個技巧,關鍵在於明白c陣列的...

學習筆記 樹狀陣列

以下 為樹狀陣列最常用的幾個操作 1.low bi t mathrm lowbit function lowbit x longint int64 begin exit x and x end 2.單點修改 procedure replace x,y int64 var i int64 begin ...