線段樹
二叉搜尋樹
,與區間樹
相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。
使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度為o(logn)。
對於線段樹中的每乙個非
葉子節點
[a,b],它的左兒子表示的區間為[a,(a+b)/2],右兒子表示的區間為[(a+b)/2+1,b]。因此線段樹是
平衡二叉樹
,最後的子節點數目為n,即整個線段區間的長度。
線段樹有兩種:一是點更新,另乙個是段更新。
一、點更新
1 求和
void pushup(int rt)
2 建樹
void build(int l, int r, int rt)
else
}
3 更新
void update2(int p, int add, int l, int r, int rt)
}
4 查詢
int query(int l, int r, int l, int r, int rt)
int sum = 0;
int mid = (l + r) >> 1;
if(l <= mid)
sum += query(l, r, lson);
if(r >= mid + 1)
sum += query(l, r, rson);
return sum;
}
二、段更新
1 求和
void pushup(long long rt)
2 向下加
void pushdown(long long rt, long long len)
}
3 建樹
void build(long long l, long long r, long long rt)
long long mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
4 更新
void update2(long long l, long long r, long long add, long long l, long long r, long long rt)
pushdown(rt, r - l + 1);
long long mid = (l + r) >> 1;
if(l <= mid)
update2(l, r, add, lson);
if(r >= mid +1)
update2(l, r, add, rson);
pushup(rt);
}
5 查詢
long long query(long long l, long long r, long long l, long long r, long long rt)
pushdown(rt, r - l + 1);
long long sum = 0;
long long mid = (l + r) >> 1;
if(l <= mid)
sum += query(l, r, lson);
if(r >= mid + 1)
sum += query(l, r, rson);
return sum;
}
經典例題
a - curious robin hood lightoj - 1112 點更新
b - horrible queries lightoj - 1164 段更新
感覺就是模板,段更新利用了lazy的思想,不用不加
線段樹理解
當我覺得我學習演算法剛剛從萌新到入門的時候,一類給定乙個區間然後給定一系列操作的題徹底的打擊了我,那時我才醒悟,程式設計路上,我一直是萌新。線段樹是乙個具有樹特性的資料結構,它是一顆二叉搜尋樹。如下圖為區間 1,10 所建立的線段樹 將每乙個區間序列二分成小區間,線段樹就儲存小區間的資訊,也就是每個...
線段樹初步理解
原本這兩天在搞網路流的.但最近幾次網賽多次遇到了線段樹的題目.意識到線段樹還是重要的.所以今天就初步的了解了線段樹最簡單的應用.單點更新.今天學習線段樹主要是看notonlysuccess大牛的模板 風格非常好.很適合初學線段樹的來參考.網上的一些ppt也不錯.一步一步動態描述線段樹的演算法過程.線...
理解 線段樹 掃瞄線
題目大意 給你n個矩形,求他們的總面積之和。解題思路 哈哈,不過大家別急,為了方便描述,自己動手畫了幾個。四條紅線為矩形的上下底邊,這裡我們稱之為掃瞄線 實際程式設計中不存在,只是乙個概念 如圖所示,要求兩個矩形的面積並,可以把矩形分成幾個小矩形,最後的面積總和為它們的和。對於每個小矩形其 面積s ...