資料結構 線段樹

2022-05-12 03:48:08 字數 2471 閱讀 5981

摘自《演算法競賽高階指南》。

線段樹是一種基於分治思想的二叉樹結構,用於在區間上進行資訊統計。

線段樹的基本特徵:

1.線段樹的每個節點都代表乙個區間。

2.線段樹具有唯一的根節點,代表的區間是整個統計範圍,如[1,n]。

3.線段樹的每個葉節點都代表乙個長度為1的元區間[x,x]。

4.對於每個內部節點[l,r],它的左子節點是[l,mid],右子節點是[mid+1,r],其中mid=(l+r)/2(向下取整)。

線段樹的節點編號方法:「父子二倍」節點編號法

1.根節點編號為1。

2.編號為x的節點的左子節點的編號為x*2,右子節點編號為x*2+1。

注意:儲存線段樹的陣列長度要不小於4n才能保證不會越界。(n為葉節點數)

struct

segmentreet[n*4];//

struct陣列儲存線段樹

void build(int p,int l,int

r)//

葉節點

int mid=(l+r)/2;//

折半 build(p*2,l,mid);//

左子節點[l,mid],編號p*2

build(p*2+1,mid+1,r);//

右子節點[mid+1,r],編號p*2+1

t[p].dat=max(t[p*2].dat,t[p*2+1].dat);//

從下往上傳遞資訊

} build(

1,1,n);//

呼叫入口

void change(int p,int x,int

v)//

找到葉子結點

int mid=(t[p].l+t[p].r)/2

;

if(x<=mid)change(p*2,x,v);//

x屬於左半區間

else change(p*2+1,x,v);//

x屬於右半區間

t[p].dat=max(t[p*2].dat,t[p*2+1].dat);//

從下往上更新資訊

} change(

1,x,v);//

呼叫入口

從根節點開始,遞迴執行以下過程:

1.若[l,r]完全覆蓋了當前節點代表的區間,則立即回溯,並且該節點的dat值為候選答案。

2.若左子節點與[l,r]有重疊部分,則遞迴訪問左子節點。

3.若右子節點與[l,r]有重疊部分,則遞迴訪問右子節點。

int ask(int p,int l,int

r) cout

<1,l,r)呼叫入口

【例題1】:你能回答這些問題嗎

【例題2】:區間最大公約數

我們在修改指令時,可以在l≤pl≤pl≤r的情況下立即返回,只不過在回溯之前向節點p增加標記,標識「該節點曾經被修改,但其子節點尚未被更新」。

在後續的指令中,需要從節點p向下遞迴,我們再檢查p是否具有標記。若有標記,就根據標記資訊更新p的兩個子節點,同時為p的兩個子節點增加標記,然後清除p的標記。

這樣一來,每條修改的指令的時間複雜度從o(n)降到了o(log n)。

【例題】:乙個簡單的整數問題

主要**如下:

#define 100000+10

struct

n segmenttreetree[n*4

];int

a[n],n,m;

void build(int p,int l,int

r)

int mid=(l+r)/2

; build(p*2

,l,mid);

build(p*2+1,mid+1

,r);

sum(p)=sum(p*2)+sum(p*2+1

);}

void spread(intp)}

void change(int p,int l,int r,int

d) spread(p);

//下傳延遲標記

int mid=(l(p)+r(p))/2

;

if(l<=mid)change(p*2

,l,r,d);

if(r>mid)change(p*2+1

,l,r,d);

sum(p)=sum(p*2)+sum(p*2+1);}

long

long ask(int p,int l,int

r)int

main()

else cout<1

,l,r);

}}

【例題1】:亞特蘭蒂斯

【例題2】:窗內的星星

資料結構 線段樹

啦啦啦啦啦啦線段樹是個好東西 好吧並沒有什麼好的 但貌似還是很好啊 線段樹就是一棵樹!顧名思義 又是這個詞 就是求關於一段的某些什麼什麼東西。比如區間最大值啊什麼的。引用百科知識 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中...

資料結構 線段樹

一 目標 1.如何快速的查詢出下列陣列arr 2,5 的和 2。以及更新arr 4 為6。用普通的方法查詢的複雜度為o n 更新的複雜度為o 1 這時候我們可以用線段樹來快速完成這些操作,複雜度為logn。二 內容 如何建立,查詢,更新線段樹。public class qurqpd int tree...

資料結構 線段樹

線段樹是一顆平衡的二叉搜尋樹,他以空間換區時間,讓線性查詢加速log級別的查詢,用到的演算法主要是二分搜尋和遞迴。例如 有陣列data 我有乙個需求,我需要頻繁的查詢區間i j的sum和。這裡先給出兩個解決方案 如果使用最普通的演算法遍歷,那麼查詢和更新的複雜度為o n 當然你還可以使用動態規劃,定...