樹狀陣列在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)此外,從任意節點x出發,想要不重不漏地遍歷1~x號元素只需要://注: int lowbit(int 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 #includep3374#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;
}
既然有字首和,對應地就可以運用差分解決如下問題:
可以將樹狀陣列的效果簡單地總結為:對一串行進行頻繁區域性(單點)操作時,在任意時刻都可以快速求取當前序列的任意字首和.
p1908 逆序對
如利用桶的思想,將數x置入桶c[x]中時,檢查c[x+1~n]之和,即得新產生的逆序數.
樹狀陣列滿足了隨時查詢字首和的操作.
需要處理一些細節,還有離散化.
#include #includep1908#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;
}
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 的複雜度下進行範圍修改,但是這時只能查詢其中乙個元素的值。一,改點...