理解線段樹

2021-07-31 08:20:08 字數 2086 閱讀 6727

線段樹

二叉搜尋樹

,與區間樹

相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。

使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度為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 ...