OI學習筆記 樹狀陣列

2022-05-24 09:15:09 字數 2868 閱讀 4186

花了乙個上午,終於把樹狀陣列弄懂了。。。

打了三種樹狀陣列的模板:樹狀陣列單點更新區間查詢,線段樹區間更新單點查詢,樹狀陣列區間更新區間查詢。

第三種太毒了,,,好久才明白

就是樹一樣的陣列,它的底層實現其實就是乙個陣列,但是我們把它yy成了一棵樹。。。

他的每一列的最頂端有乙個元素,而其他位置都是我們yy出來的,他在程式中並不會出現,

每乙個非葉子節點都是他兩個子節點儲存資訊的綜合(可以是和,乘積或最大值等等)。

樹狀陣列用來求字首和,如果你想求任意的區間和則用兩個字首和只差即可

lowbit[i]定義為:點i所「支配」的葉子節點的個數

怎麼理解呢?比如說:上圖中lowbit[2]=2,lowbit[4]=4,lowbit[7]=1(葉子節點算1)

然後,我們驚人地發現:乙個點的父節點和這個點的橫向距離,乙個點和他左邊那個區間節點的橫向距離,都是這個節點的lowbit!

這樣,我們就可以用lowbit很方便地從乙個區間轉移到另乙個包含它的區間了!

舉個栗子:

第一種:從1依次轉移到2,4,8:

第二種:從7依次轉移到6,4:

向右轉移:在剛才第一種轉移的過程中,我們可以完成用子節點更新父節點的值(剛才更新了1,2,4,8)

向左轉移:而在第二種轉移中,可以完成對一段字首和的統計(剛才統計的區間[1,7])

那麼,lowbit[i]怎麼求呢?這裡直接寫乙個結論:

lowbit[i]=i&(-i)

這個比較簡單,按照上面的方法結合lowbit公式一步一步轉移即可

**:

#include#define lowbit(x) (x&(-x))

using

namespace

std;

const

int maxn=10010

;int

c[maxn],n,m;

void change(int x,int

num)

}int ask(int

x)

returns;}

intmain()

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

else

}return0;

}

區間更新這要記住:原序列用普通陣列a存起,更新區間時跑向左轉移,標記更新的數值(比如說加多少,乘多少,變成多少等等)

(剛剛更改的範圍是乙個[1,y],如果你要更改[x,y]別忘記把前面不要的[1,x-1]部分減回來!!!)

然後查詢點時只要向右轉移,按照剛剛打的標記更改即可。(是不是和線段樹的lazytag有點像呢)

以下是**:

#include#define lowbit(x) (x&(-x)) 

using

namespace

std;

const

int maxn=10010

;int

a[maxn],n,m,c[maxn];

void change(int x,int

num)

}int ask(int

x)

return rxz+a[x];

}int

main()

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

else

}return0;

}

這個有點難想。

我們考慮原數列a的差分陣列c

差分陣列有乙個性質:差分陣列跑一遍字首和,得到原陣列。

可以得到:

這樣,豈不是可以用差分陣列c[i]來表示a[i]?

我們只要用乙個額外的陣列來儲存

就行了.

程式設計時要注意初始化

**:(d陣列為儲存

的陣列)

#include#define lowbit(x) x&(-x)

using

namespace

std;

const

int maxn=10010

;int

n,m,a[maxn];

int c[maxn],d[maxn];//

差分陣列&陣列d[i]=(i-1)c[i];

void changesection(int x,int

num)

}int asksection(int x)

returns;}

intmain()

else

}return0;

}

OI學習筆記之資料結構 樹狀陣列

樹狀陣列複雜度 o logn 樹狀陣列是一種維護字首和,區間最大值,區間最小值,區間異或和等滿 換律的東西的資料結構,其支援單點修改和區間查詢。樹狀陣列其實並不算一棵樹,它是由陣列 二進位制的操作實現的,只是在實現的過程中我們借助了樹形結構的思想,因此樹狀陣列並不需要建樹等操作。一,認識樹狀陣列 樹...

學習筆記 樹狀陣列

以下 為樹狀陣列最常用的幾個操作 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 ...

樹狀陣列學習筆記

在學習完了線段樹後,聽說樹狀陣列能寫的題,線段樹都能做,所以一直沒有詳細的學習樹狀陣列 直到碰到了一道卡線段樹的題目,因為線段樹運用了很多遞迴,所以常數比較大,容易被卡 現在總結一下樹狀陣列 1 樹狀陣列個人認為就是字首和演變而來的 2 單點更新 當你要更新某個點的值時,你要從下面到上面依次更新過去...