線段樹學習筆記

2021-10-24 05:39:22 字數 2212 閱讀 1015

線段樹:

線段樹其實是乙個二叉搜尋樹,它儲存的是乙個區間的資訊

每個節點以結構體的方式儲存

結構體包括區間的左右端點外加區間和

其它看情況加區間要維護的資訊

線段樹的基本思想是二分

特殊性質有:

每個節點的左孩子的區間範圍確定

對於節點k,左孩子節點為2k,右孩子為2k+1,這符合完全二叉樹的性質

線段樹的基本操作:建樹,單點查詢,單點修改,區間查詢,區間修改

1.建樹

struct node

tree[

4*n+1]

;

樹應該開4倍空間

主體思路

對於二分到的結點,給他左右端點確定範圍

如果是葉子結點,儲存要維護的資訊

狀態合併

void

creat_tree

(int l,

int r,

int k)

int m=

(l+r)/2

;creat_tree

(l,m,k*2)

;creat_tree

(m+1

,r,k*2+

1); tree[k]

.sum=tree[

2*k]

.sum+tree[k*2+

1].sum;

}

2.單點查詢

如果左端點等於右端點則是葉節點,是我們要查詢的值,直接返回該值即可

如果不相等則求出其左右端點的中間值,如果比mid小遞迴左孩子,否則遞迴右孩子

int

find_tree

(int k)

int mid=

(tree[k]

.l+tree[k]

.r)/2;

if(k<=mid)

else

return

find_tree

(k*2+1

);//否則找右孩子

}

3、單點修改

原理=單點查詢+建樹的結合

void

changdata

(int k,

int y)

//k要查詢的位置,y是要增加的值

int m=

(tree[k]

.l+tree[k]

.r)/2;

if(x<=m)

changdata(2

*k,y)

;else

changdata(2

*k+1

,y);

tree[k]

.sum=tree[k*2]

.sum+tree[k*2+

1].sum

}

4.區間查詢

int ans=0;

void

sum(

int k,

int x,

int y)

int m=

(tree[k]

.l+tree[k]

.r)/2;

if(x<=m)

sum(

2*k,x,y);if

(y>m)

sum(

2*k+

1,x,y)

;}

5、區間修改

引入懶惰標記

void

down

(int k)

void

add(

int k)

if(tree[k]

.f)down

(k);

//懶標記下傳。只有不滿足上面的if條件才執行,所以一定會用到當前節點的子節點

int m=

(tree[k]

.l+tree[k]

.r)/2;

if(a<=m)

add(k*2)

;if(b>m)

add(k*2+

1); tree[k]

.w=tree[k*2]

.w+tree[k*2+

1].w;//更改區間狀態

}

線段樹學習筆記

線段樹是一種 二叉搜尋樹 與區間樹 相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度為o logn 而未優化的 空間複雜度 為2n,因此有時需要離散化讓空間壓縮。以下筆記摘自lcomyn神犇部落格 1....

線段樹學習筆記

本文筆記在參考一步一步理解線段樹 tenos的基礎上形成 線段樹,也是二叉搜尋樹的一種,是基於陣列,但是優於陣列的一種資料結構。同時結合預處理 時間複雜度一般在o n 使得從原來陣列的o n 的查詢和更新複雜度降到了o logn 在處理很大資料量的資料更新和查詢最值方面變得簡單,值得一提的是,它的構...

線段樹學習筆記

線段樹是一種維護區間的資料結構,且滿足二叉樹的全部性質 下圖是一棵維護區間 1 6 1,6 的線段樹 格式 idl ri dl r我們可以發現,對於每個節點 k k 來說,其左節點編號為2k role presentation style position relative 2k2 k,右節點編號為...