參考部落格:
戳這裡還有這裡
這裡這裡
樹狀陣列的用途就是維護乙個陣列,重點不是這個陣列,而是要維護的東西,最常用的求區間和問題,單點更新。但是某些大牛yy出很多神奇的東西,完成部分線段樹能完成的功能,比如區間更新,區間求最值問題。
樹狀陣列當然是跟樹有關了,但是這個樹是怎麼構建的吶?這裡就不得不感嘆大牛們的腦洞之大了,竟然能想出來用二進位制末尾零的個數多少來構建樹以下圖為例:
從上圖能看出來每乙個數的父節點就是右邊比自己末尾零個數多的最近的乙個,也就是x的父節點就是x+(x&(-x)),這裡為什麼可以參考計算機位運算,x&(-x)就能得出自己末尾0的個數例如10&(-10)=(0010)二進位制。每乙個節點儲存的就是以他為根節點的數的和,這樣就得出來了更新樹狀陣列的函式:
int lowbit(int x)x-(x&(-x))剛巧是前乙個棵樹的根節點,這樣就能求出1到x和,以x=9為例,9&(-9)=1;這樣x-(x&(-x))=8,剛巧是前一棵樹的根節點。void uodate(int x)
return s;
}
例題:poj 2352 stars
/*
題意給你n個星星的座標,每乙個星星的等級為:在不在這個星星右邊並且不比這個星星高的星星的個數view code然後出處每個等級星星的個數
樹狀陣列,一開始把上乙個題的模板扒過來的......真是傷啊,這個題更新點的時候要把右邊的點更新到maxn要不然會漏掉條件的
*/#include#include#include#include#include#define n 32010
using namespace std;
int n;
int c[n];
int cur[n];//統計每個等級的星星
int lowbit(int x)
int getx(int x)
return ans;
}void update(int x)
}int main()15}
16 ll sigma(ll *r, ll pos)
1722
intmain()
2332 scanf("
%lld
",&q);
33while(q--)
3442
if(type==2)43
49}50return0;
51 }
接著就是rmq演算法,用來求區間最值,直接求當然是不現實的,因為資料很多的時候,複雜度太高,這樣就要先進性預處理,dp[i][j]表示從i開始2^j範圍內的最值,這樣能推出狀態轉移方程dp[i][j]=max(dp[i][j-1],dp[i+(1<
首先是預處理部分:
void rmq_init(int n)}int rmq(int l,int r)
int main()
rmq_init(n);
for(int i=1;i<=m;i++)
return 0;
}
樹狀陣列總結
樹狀陣列的基本知識已經被各種大牛和菜鳥講到爛了,我就不多說了,下面給出基本操作的 假定原陣列為a 1.n 樹狀陣列b 1.n 考慮靈活性的需要,使用int a傳陣列。define lowbit x x x int sum int a,int x void update int a,int x,int...
樹狀陣列總結
樹狀陣列是對乙個陣列改變某個元素和求和比較實用的資料結構。兩中操作都是o logn 在解題過程中,我們有時需要維護乙個陣列的字首和s i a 1 a 2 a i 但是不難發現,如果我們修改了任意乙個a i s i s i 1 s n 都會發生變化。可以說,每次修改a i 後,調整字首和s在最壞情況下...
樹狀陣列總結
今天學習了一下樹狀陣列,做乙個簡單總結。樹狀陣列可分為兩種操作,1 修改單個點,統計區間和 一般為 向上修改 update1 向下統計 sum1 2 修改區間,統計單個點 一般為向下修改 update2 向上統計 sum2 主要模板如下 int c n int lowbit int x 用於確定區間...