線段樹學習筆記

2021-08-18 02:24:31 字數 2964 閱讀 7697

線段樹是一種維護區間的資料結構,且滿足二叉樹的全部性質

下圖是一棵維護區間[1

,6] [1,

6]的線段樹↓

格式:idl

,ri dl

,r我們可以發現,對於每個節點

k k

來說,其左節點編號為2k

' role="presentation" style="position: relative;">2k2

k,右節點編號為2k

+12 k+

1,左節點維護區間[l

,(l+

r)/2

] [l,

(l+r

)/2]

,右節點維護區間[(

l+r)

/2+1

,r] [(l

+r)/

2+1,

r]這樣我們就得到了遞迴建樹的偽**:

build(k,l,r)

if(l=r)

獲取節點資訊

return

i←2k,mid←(l+r)/2

build(i,l,mid)

build(i+1,mid+1,r)

合併子節點資訊

end

然後我們考慮區間查詢操作

比方說我要查詢區間[1

,4] [1,

4]的資訊

我們只需要獲取節點

2 2

與節點12' role="presentation" style="position: relative;">12

12的資訊,就可以通過合併資訊的方式獲取到整塊區間的資訊

這一步也是可以遞迴求解的,只需要對維護區間判斷即可,下面給出偽**

ask(k,l,r,le,ri)

if(le<=l and r<=ri) return 節點k資訊

i←2k,mid←(l+r)/2

sum←null

if(le<=mid) 合併sum,ask(i,l,mid,le,ri)

if(mid

sum,ask(i+1,mid+1,r,le,ri)

return

sum資訊

end

如果要進行區間修改呢?

我們仍以修改[1

,4] [1,

4]為例

我們需要修改節點

2 2

與節點

12' role="presentation" style="position: relative;">12

12的資訊,並將修改計入上層節點的貢獻

對於多個標記貢獻與順序有關的情況,我們採用標記下傳的方式解決,下面是偽**

po(k,l,r)

if(l=r or 當前節點沒有標記) return

標記下傳

清空當前層標記

endcchg(k,l,r,le,ri)

po(k,l,r)

if(le<=l and r<=ri)

修改當前節點

return

i←2k,mid←(l+r)/2

cchg(i,l,mid,le,ri)

cchg(i+1,mid+1,r,le,ri)

合併下層節點資訊

end

這樣,我們就解決了序列區間修改與查詢的問題

那麼以線段樹2為例,我們給出c++的**↓

#include

#include

#include

#include

using

namespace

std;

const

int maxn=1

<<17;

int n,m,mod,x,p,l,r;

int a[maxn];

long

long tree[maxn<<1],add[maxn<<1],mul[maxn<<1];

void build(int k,int l,int r)int i=k<<1,mid=l+r>>1;

build(i,l,mid);

build(i|1,mid+1,r);

tree[k]=tree[i]+tree[i|1];

}void po(int k,int l,int r)

void cadd(int k,int l,int r,int le,int ri,int x)int i=k<<1,mid=l+r>>1;

if(le<=mid) cadd(i,l,mid,le,ri,x);

if(mid1,mid+1,r,le,ri,x);

tree[k]=(tree[i]+tree[i|1])%mod;

}void cmul(int k,int l,int r,int le,int ri,int x)int i=k<<1,mid=l+r>>1;

if(le<=mid) cmul(i,l,mid,le,ri,x);

if(mid1,mid+1,r,le,ri,x);

tree[k]=(tree[i]+tree[i|1])%mod;

}long

long ask(int k,int l,int r,int le,int ri)

void init()

void solve()return;

}int main()

線段樹學習筆記

線段樹是一種 二叉搜尋樹 與區間樹 相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度為o logn 而未優化的 空間複雜度 為2n,因此有時需要離散化讓空間壓縮。以下筆記摘自lcomyn神犇部落格 1....

線段樹學習筆記

本文筆記在參考一步一步理解線段樹 tenos的基礎上形成 線段樹,也是二叉搜尋樹的一種,是基於陣列,但是優於陣列的一種資料結構。同時結合預處理 時間複雜度一般在o n 使得從原來陣列的o n 的查詢和更新複雜度降到了o logn 在處理很大資料量的資料更新和查詢最值方面變得簡單,值得一提的是,它的構...

線段樹學習筆記

線段樹的構造 void build node cur,int l,int r else cur leftchild cur rightchild null 線段樹的查詢 int query node cur,int l,int r 線段樹的延遲修改 void change node cur,int ...