資料結構之 線段樹 1

2021-08-31 06:20:51 字數 2172 閱讀 1751

線段樹是acm中比較常見的資料結構,它的每一點都代表了一條線段[a,b],長度為1的為元線段,所有葉子結點的長度均為1。長度範圍為[1,l]的一顆線段樹的深度為log(l-1)+1。

線段樹基本的應用時查詢某段的和,最大最小值,成段更新,保證每次操作的複雜度為log(n)。

關於線段樹的文章有很多,大家可以參考

在這裡,我用hdu和poj上面的一些關於線段樹的簡單應用做為例題講解。

hdu1166(單點更新,區間求和):

敵軍海岸線上排列有n個營地,每個營地有若干個士兵,每個營地的士兵都是在隨時變動(增加或減少),要隨時求出任意兩個營地之間的士兵人數之和。

首先構造線段樹的結構:

struct seg_tree

}tt[max*4];//max是營地個數,一般線段樹的結點為它的4倍

然後就是建立線段樹:

int build(int left,int right,int idx)//idx從1開始

對於某個營地增加或減少士兵,有更新操作:

void update(int id,int x,int idx)

查詢某段營地士兵數量總和:

int query(int left,int right,int idx)

hdu1754(單點更新,區間最值):

老師喜歡問學生a到學生b中最好的成績是多少,其間,還會更改某些學生的成績。

建立線段樹:

int bulid(int left, int right, int idx)

對於某個學生成績的更改,有更新操作: 

void update(int id, int value, int idx)		//更新點,同時更新區間最值:先更新左右子樹的最值,然後更新父節點

int mid = tt[idx].calmid();

if(id <= mid)

update(id,value,ll(idx));

else

update(id,value,rr(idx));

tt[idx].value = max(tt[ll(idx)].value, tt[rr(idx)].value);

}

查詢某段學生成績中的最大值:

int query(int left, int right, int idx)

以上兩道例題是對於單點更新,對於成段更新,有hdu1698:

dota裡面有一種鉤子,它由n段組成,剛開始全部是銅的,每段重量為1。現在要把其中a-b這段換成金的或者銀的(重量分別為3,2),查詢這個鉤子的總重量。

建立線段樹:

void build(int left, int right, int idx)

更新a-b段的鉤子:

void update(int left, int right, int value, int idx)		//更新區間

if(tt[idx].value != -1)

int mid = tt[idx].calmid();

if(left <= mid)

update(left,right,value,ll(idx));

if(mid < right)

update(left,right,value,rr(idx));

}

查詢某段鉤子的重量:

int query(int left, int right, int idx)

} int mid = tt[idx].calmid();

if(right <= mid)

return query(left,right,ll(idx));

else if(left > mid)

return query(left,right,rr(idx));

else

return query(left,mid,ll(idx)) + query(mid+1,right,rr(idx));

}

學習線段樹,要熟悉線段樹的構造,查詢,更新操作。

資料結構之線段樹

線段樹也叫區間樹,顧名思義,線段樹是一種基於區間的樹,每個節點表示乙個 線段 或 區間 樹的根節點表示是 整體 的區間,左右子樹分別表示這個區間的左半邊和右半邊。function 以節點v為根建樹 v對應區間為 l,r 線段樹的關鍵在於如何定義樹節點,以及如果構建 插入 樹節點。1.樹節點的定義 p...

資料結構之線段樹

一 引例 有m個數排成一列,做n次操作,每次操作包括 1 詢問指定區間的最大值 最小值 2 將指定區間的每個數加上乙個值 如果按照最樸素的做法,乙個個的遍歷,時間複雜度 o mn 那麼如何解決乙個區間求和 最大值,最小值 的問題呢?那麼就要用到線段樹啦。二 定義 線段樹是一種二叉搜尋樹,與區間樹相似...

資料結構之線段樹

線段樹是一種二叉查詢樹,它將乙個區間劃分為1個個單元,樹的每個節點都是1個單元。如下圖的樹就是一顆區間樹。性質 對於線段樹中的每乙個非葉子節點 a,b 它的左節點為 a,a b 2 右節點為 a b 2 1,b 線段數是平衡二叉樹,子節點的個數等於整個區間的長度。建樹 在這裡,我們使用陣列來實現簡單...