線段樹是一種維護區間的資料結構,且滿足二叉樹的全部性質
下圖是一棵維護區間[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 ...