儲存結構是怎樣的?
線段樹是一種二叉樹,當然可以像一般的樹那樣寫成結構體,指標什麼的。
但是它的優點是,它也可以用陣列來實現樹形結構,可以大大簡化**。
陣列形式適合在程式設計競賽中使用,在已經知道線段樹的最大規模的情況下,直接開足夠空間的陣列,然後在上面建立線段樹。
簡單的記法: 足夠的空間 = 陣列大小n的四倍。
實際上足夠的空間 = (n向上擴充到最近的2的某個次方)的兩倍。
舉例子:假設陣列長度為5,就需要5先擴充成8,8*2=16.線段樹需要16個元素。如果陣列元素為8,那麼也需要16個元素。
所以線段樹需要的空間是n的兩倍到四倍之間的某個數,一般就開4*n的空間就好,如果空間不夠,可以自己算好最大值來省點空間。
怎麼用陣列來表示一顆二叉樹呢?假設某個節點的編號為v,那麼它的左子節點編號為2*v,右子節點編號為2*v+1。
然後規定根節點為1.這樣一顆二叉樹就構造完成了。通常2*v在**中寫成 v<<1 。 2*v+1寫成 v<<1|1 。
以下以維護數列區間和的線段樹為例,演示最基本的線段樹**。
(0)定義:
#define maxn 100007 //
元素總個數
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
intsum[maxn<<2],add[maxn<<2];
//sum
求和,add
為懶惰標記
inta[maxn],n;
//存原陣列資料下標
[1,n]
(1) 建樹:
(2)
//pushup
函式更新節點資訊
,這裡是求和
(3)voidpushup(intrt)
(4)
//build
函式建樹
(5)voidbuild(intl,intr,intrt)
(10)intm=(l+r)>>1;
(11)
//左右遞迴
(12) build(l,m,rt<<1);
(13) build(m+1,r,rt<<1|1);
(14)
//更新資訊
(15) pushup(rt);
(16) }
(2)點修改:
假設a[l]+=c:
1.voidupdate(intl,intc,intl,intr,intrt)
6.intm=(l+r)>>1;
7.
//根據條件判斷往左子樹呼叫還是往右
8.if(l <= m) update(l,c,l,m,rt<<1);
9.elseupdate(l,c,m+1,r,rt<<1|1);
10. pushup(rt);//
子節點更新了,所以本節點也需要更新資訊
11. }
(3)區間修改:
voidupdate(intl,intr,intc,intl,intr,intrt)
intm=(l+r)>>1;
pushdown(rt,m-l+1,r-m);
//下推標記
//這裡判斷左右子樹跟
[l,r]
有無交集,有交集才遞迴
if(l <= m) update(l,r,c,l,m,rt<<1);
if(r > m) update(l,r,c,m+1,r,rt<<1|1);
pushup(rt);
//更新本節點資訊
}
(4)區間查詢:
詢問a[l,r]的和
首先是下推標記的函式:
1.voidpushdown(intrt,intln,intrn)
13. }
然後是區間查詢的函式:
intquery(intl,intr,intl,intr,intrt)
intm=(l+r)>>1;
//下推標記,否則
sum可能不正確
pushdown(rt,m-l+1,r-m);
//累計答案
intans=0;
if(l <= m) ans+=query(l,r,l,m,rt<<1);
if(r > m) ans+=query(l,r,m+1,r,rt<<1|1);
returnans;
}
(5)函式呼叫:
//建樹
build(1,n,1);
//點修改
update(l,c,1,n,1);
//區間修改
update(l,r,c,1,n,1);
//區間查詢
intans=query(l,r,1,n,1);
線段樹基礎詳解
儲存結構是怎樣的?線段樹是一種二叉樹,當然可以像一般的樹那樣寫成結構體,指標什麼的。但是它的優點是,它也可以用陣列來實現樹形結構,可以大大簡化 陣列形式適合在程式設計競賽中使用,在已經知道線段樹的最大規模的情況下,直接開足夠空間的陣列,然後在上面建立線段樹。簡單的記法 足夠的空間 陣列大小n的四倍。...
線段樹 詳解
acm刷題時遇到許多連續區間的動態查詢問題,例如求取某一區間上元素之和 求取某一區間上元素的最大值,此時如果使用一般的方法求解會使得時間超出要求。此時需要使用到線段樹,其主要用於高效解決連續區間的動態查詢問題。線段樹,類似區間樹,是乙個完全二叉樹,它在各個節點儲存一條線段 陣列中的一段子陣列 由於二...
線段樹詳解
線段樹是處理區間問題的好的解決方法,當有n個元素時對區間的操作可以在o logn 時間內完成,有q個詢問也不會超時,根據節點維護的資料的不同,線段樹可以提供不同的功能,下面以rang minimum query rmq,即查詢區間內最小值 為例,進行說明。對於陣列,線段樹結構為 其維護區間與儲存下標...