關於線段樹和樹狀陣列的一些知識集合

2021-09-25 12:47:12 字數 2382 閱讀 1663

這是昨天大佬講的一些演算法,我自己整理了一些,順序有點凌亂,下面還有一些網上大佬們的資料,可以當作消遣看一看。

今天也是努力學習的菜雞啊qaq

個人覺得線段樹這裡還是不難理解的,只是我還不會**實現(哭遼?)

菜雞要努力啊!衝鴨!

下面是正文部分:

有根數:根是確定樹中乙個點作為根 靠近根的為「父」 遠離根的為「子」。

二叉樹 只有兩個分支的樹 分為左分支和右分支 有序的

每個節點可以有不同的含義

(例如:可以代表乙個區間的和,最大值,最小值等)可以存在標記(標記下放*不太懂)

若節點為(a,b) 左節點(a,(a+b)/2) 右節點((a+b)/2+1,b)

每層最多有兩個終止節點(*)

標號的概念:即儲存每個節點資料的陣列下標

*3.標記下放

ex:求ai-aj 的和 其中每個點都加n (標記在節點中儲存)

重要**實現;(c++)

using namespace std;

void xg(int x)

}

(以上是自我筆記)

網上資料:

給定區間【l,r】,如何分解成上述給定的區間?

對於給定區間[2,12]要如何分解成上述區間呢?

分解方法一:自下而上合併——利於理解

先考慮樹的最下層,將所有在區間[2,12]內的點選中,然後,若相鄰的點的直接父節點是同乙個,那麼就用這個父節點代替這兩個節點(父節點在上一層)。這樣操作之後,本層最多剩下兩個節點。若最左側被選中的節點是它父節點的右子樹,那麼這個節點會被剩下。若最右側被選中的節點是它的父節點的左子樹,那麼這個節點會被剩下。中間的所有節點都被父節點取代。對最下層處理完之後,考慮它的上一層,繼續進行同樣的處理。

*** 怎麼用陣列來表示一顆二叉樹呢?假設某個節點的編號為v,那麼它的左子節點編號為2v,右子節點編號為2v+1。

然後規定根節點為1.這樣一顆二叉樹就構造完成了。通常2v在**中寫成 v<<1 。 2v+1寫成 v<<1|1 。

線段樹**實現:

定義//

#define maxn 100007

int a[maxn],n,n;//原陣列,n為原陣列元素個數 ,n為擴充元素個數

int sum[maxn<<2];//區間和

int add[maxn<<2];//懶惰標記

建樹:

void build(int n)

} ????

//pushup函式更新節點資訊,這裡是求和

void pushup(int rt) (求每個節點的資料)

//build函式建立線段樹

void build(int l,int r,int rt)

int m=(l+r)>>1(求中間值);

//左右遞迴

build(l,m,rt<<1); (建立左分支)

build(m+1,r,rt<<1|1); (建立右分支)

//更新資訊

pushup(rt);

}功能:點修改

void update(int l,int c,int l,int r,int rt)

int m=(l+r)>>1;

//根據條件判斷往左子樹呼叫還是往右

if(l <= m) update(l,c,l,m,rt<<1);

else update(l,c,m+1,r,rt<<1|1);

pushup(rt);//子節點的資訊更新了,所以本節點也要更新資訊

}

功能:區間查詢

int query(int l,int r,int l,int r,int rt)

int m=(l+r)>>1;

//左子區間:[l,m] 右子區間:[m+1,r] 求和區間:[l,r]

//累加答案

int ans=0;

if(l <= m) ans+=query(l,r,l,m,rt<<1);//左子區間與[l,r]有重疊,遞迴

if(r > m) ans+=query(l,r,m+1,r,rt<<1|1); //右子區間與[l,r]有重疊,遞迴

return ans;

}樹狀陣列:

c(2)=1對應二進位制**+lowbit(1);

c(4)=2對應二進位制**+lowbit(2)其他同

**實現:

int lowbit(int x)

void buildtree()

}void add(int k, int d)

int sum(int s, int t)

樹狀陣列和線段樹

主要解決兩個問題 其他問題可以轉化 更新某一點的值 求區間值 時間按複雜度 logn 原陣列a 1 a 2 a n 寫成樹狀陣列c c x x lowbit x x 左開右閉 筆記 主要 const int n int tr n int lowbit int x void add int x,int...

線段樹和樹狀陣列

引入1 有n個數 n 50000 個數,m m 50000 次詢問。每次詢問區間l到r的數的和。要求輸出每一次詢問的結果.分析 1.用字首和問題進行求解 再開乙個陣列 暫且記為b n 設n個數所組成的陣列為a n b i 用來記錄從a 1 到a i 的所有數字的和 即 b 1 a 1 b 2 b 1...

線段樹和樹狀陣列

線段樹 segment tree 和樹狀陣列是兩種常用的資料結構。他們用來維護乙個區間內的操作,可以在 logn 的複雜度上進行查詢和修改。線段樹可以維護對乙個區間的查詢和修改,可以對區間進行分塊查詢,而樹狀陣列是線段樹的閹割版,經常用來區間查詢,但修改只能進行單點修改,經過改造之後可以區間修改,區...