線段樹入門之久久為功

2022-02-16 05:48:28 字數 1507 閱讀 6858

-------------------------------謝謝你們一直愛著我! 加油!

**實現線段樹:

(0).定義:

#define maxn 100007 //元素總個數

int sum[maxn<<2]; //sum求和,開四倍空間

int a[maxn],n; //存原陣列下標[1,n]

(1).建樹:

void pushup(int rt)   //pushup函式更新節點資訊,這裡是求和
//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); //更新資訊

}

(2).點修改:

假設a[l]+=c:

1

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

rt)6

int m=(l+r)>>1

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

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

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

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

10 }

點修改其實可以寫的更簡單,只需要把一路經過的sum都+=c就行了,不過上面的**更加規範,在題目更加複雜的時候,按照格式寫更不容易錯。

(3)區間查詢:

討論區間查詢的一種求和的情況:

詢問a[l..r]的和

注意到,整個函式的遞迴過程中,l,r是不變的。

首先如果當前區間[l,r]在[l,r]內部,就直接累加答案

如果左子區間與[l,r]有重疊,就遞迴左子樹,右子樹同理。

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;

}

---------------------------------嘻嘻,多多動手實踐之,久久為功!

線段樹入門

線段樹 interval tree 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。上圖是一棵典型的線段樹,它對區間 1,10 進行分割,直到單個點。這棵樹的特點 是 1.每一層都是區間 a,b 的乙個劃分,記 l b a 2.一共有log2l層 3.給定乙...

線段樹入門

學習下 線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為...

線段樹 入門

首先線段樹形象來說就是將陣列看成乙個線段,然後不斷的進行分割,儲存在樹中的不同節點上,有點類似於b 樹的定義吧 觀察上圖,首先將整個陣列的某種資訊 最大值或者最小值等 儲存在根節點,對應 1,8 然後對 1,8 線段進行平分,得到 1,4 和 5,8 兩個線段,掛在樹的第二層。這樣節點2儲存了陣列中...