-------------------------------謝謝你們一直愛著我! 加油!
**實現線段樹:
(0).定義:
#define maxn 100007 //元素總個數(1).建樹:int sum[maxn<<2]; //sum求和,開四倍空間
int a[maxn],n; //存原陣列下標[1,n]
void pushup(int rt) //pushup函式更新節點資訊,這裡是求和
//build函式建立線段樹
void build(int l,int r,int rt)//終止條件 若到達葉節點(2).點修改:int m=(l+r)>>1;
//左右遞迴
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt); //更新資訊
}
假設a[l]+=c:
1點修改其實可以寫的更簡單,只需要把一路經過的sum都+=c就行了,不過上面的**更加規範,在題目更加複雜的時候,按照格式寫更不容易錯。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 }
(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儲存了陣列中...