模板 樹狀陣列

2022-09-15 00:15:24 字數 2511 閱讀 3850

樹狀陣列在o(logn)時間內對陣列執行單點增加,區間和查詢.

觀察這個樹狀陣列:

其中,每個節點儲存著其橫向覆蓋的範圍內所有元素的和,如c[16]儲存1~16號元素的和,c[12]儲存9~12號元素的和.

節點x的覆蓋範圍表示為[x-lowbit(x)+1, x].

從構造這顆樹的角度來解釋其結構,描述為每個節點c[x]的父節點都可以表示為c[x+lowbit(x)].

由此可推出樹的深度為o(logn),這意味著從任意節點出發,都可以快速地遍歷其到根節點的路徑上的每乙個點:

while (x <=n) 

//注: int lowbit(int x)

此外,從任意節點x出發,想要不重不漏地遍歷1~x號元素只需要:

while (x > 0

)

以上就是樹狀陣列支援的兩種操作,複雜度都是o(logn).關於它為什麼看起來像魔法,點這裡

.由於樹狀陣列的第二種操作,它很適合用來計算字首和.

求取區間內所有數的和,使用字首和表示,故維護樹狀陣列c[i],操作1在位置x上加k,操作二計算字首和c[1~y]與c[1~x-1]並輸出兩者差值.

int lowbit(int x) 

void add(int x, int k)

}int sum(int x)

return

ret;

}

故有:

#include #include 

#include

#include

using

namespace

std;

int n, m, s[500010

];int lowbit(int x)

void add(int x, int

y) }

int sum(int

x)

return

ans;

}int

main()

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

return0;

}

p3374

既然有字首和,對應地就可以運用差分解決如下問題:

可以將樹狀陣列的效果簡單地總結為:對一串行進行頻繁區域性(單點)操作時,在任意時刻都可以快速求取當前序列的任意字首和.

p1908 逆序對

如利用桶的思想,將數x置入桶c[x]中時,檢查c[x+1~n]之和,即得新產生的逆序數.

樹狀陣列滿足了隨時查詢字首和的操作.

需要處理一些細節,還有離散化.

#include #include 

#include

#include

using

namespace

std;

struct

s } s[

500010

];int c[500010], rk[500010

], n;

inline

void add(int p, int

d) }

inline

int ask(int

p)

return

ret;

}int

main()

printf(

"%lld\n

", ans);

return0;

}

p1908

p3372 【模板】線段樹 1

由於數學是美的,兩個樹狀陣列可以過了這道題.這裡樹狀陣列的作用仍然是快速求字首和.

一篇更詳細的部落格:

樹狀陣列模板

假設有一列數 1 i n 支援如下兩種操作 1.將ai的值加d。2.輸出ai ai 1 aj 1 i j n 樹狀陣列是一種特殊的資料結構,這種資料結構的時空複雜度和線段樹相似,但是它的係數要小得多 hdu 1166 敵兵布陣 題目 a國在海岸線沿直線布置了n個工兵營地。由於採取了某種先進的監測手段...

樹狀陣列模板

已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數數加上x 2.求出某乙個數的和 這種水水的樹狀陣列,博主就不做介紹,直接上 希望大家可以多多捧場!include include include include include include include include include ...

樹狀陣列模板

樹狀陣列 binary indexed tree bit fenwick tree 是乙個查詢和修改複雜度都為log n 的資料結構。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值 經過簡單修改可以在log n 的複雜度下進行範圍修改,但是這時只能查詢其中乙個元素的值。一,改點...