1,首先它長這個樣子:
由上圖清楚看見:
c1=a1 ;c2=a1+a2;c3=a3;c4=a1+a2+a3+a4;.....依次類推
2,關於lowbit(int x)return x&(-x);
我們從圖上可以看出規律:ci=ai+ai-1....(2^k個a相加,這裡k就是i二進位制末尾0的個數);
比如說奇數(1,3,5....)二進位制末尾都是0個0,所以ci=2^0個a相加的結果;
比如8(二進位制1000)所以是8個a相加;
根據反碼的性質lowbit返回的就是2^k;
3,關於修改
int change(int x,int c)
/*
更新乙個點;我們也需要更新它的根節點;
比如:更新3,lowbit(3)=1是3的子節點數目,3+lowbit(3)就相當於3+右兄弟所有節點數==根節點了。
所以他是更新3再更新4,4的lowbit為4,更新8,最後結束迴圈(看圖)
*/4,關於查詢
int getsun(int x)
/*
對比修改,就是其逆過程;
查詢6,就是求1-6;
先re+c[6],再加上c[4]結束迴圈(看圖);
這個過程就是二進位制最後乙個1補為0的過程,所以時間複雜度就變logn了
*/5,求區間和[l,r],就是利用字首和的思想c[r]-c[l-1];
6,樹狀陣列中的差分約束
比如說有這樣的題目1,2....n的序列,有兩種操作
a:a,b表示[a,b]間序號都要塗一次色;
b,a,問a圖了幾次色
這個題更新時change(a,1),change(b+1,-1);然後直接查詢getsum(a);返回的就是單點資訊
7,二維樹狀陣列
c11=a11; c12=a11+a12;c13=a13;c14=a11+a12+a13+a14;
c12=a11+a21 a12=a11+a12+a11+a12+a21+a22;.........
和一維一樣
void change(int x,int y,int c) }}
int getsum(int x,int y)
} return re;
}
8,區間最值的維護(末端插入端點)
8.1加入乙個新節點,就要更新以該節點為根節點的樹的最值。
比如加入節點7,lowbit(7)=1;c[7]=a[7]//a[7]為節點的數值;
比如加入節點8,c[8]為其下的所有節點數值=max(a[8],c7,c[6],c[4]),lowbit(8)=8;
其直接連的節點個數分別是1(節點7),2(5,6)4(1,2,3,4);
比如16,直接連的個數是1,2,4,8;
所以我們更新的時候可以這樣寫:
void change(int r)
} return re;
}
--r是右其有起第二個節點麼如區間7-8 re=a[8]了,接下來就看7了,7-7re=max(re,re[7])的理由了。
解釋for迴圈,前面已經很多次解釋lowbit(i),就是它應該覆蓋的節點數,如果是r-l>=lowbit(r)大於等於右端點的覆蓋了
那比較c[r]就是了,再縮小範圍。
樹狀陣列總結
樹狀陣列的基本知識已經被各種大牛和菜鳥講到爛了,我就不多說了,下面給出基本操作的 假定原陣列為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 用於確定區間...