資料結構的半夜----線段樹學習筆記1
阿新 • • 發佈:2018-12-08
蒟蒻奉上一篇線段樹學習筆記(ssfd)。
曾經有個ACM Au選手嘗試往我愚笨的腦袋死命資料結構,最後還是我自己一年腦容量略大之後才真正學進去的。(羞愧)
先借個圖
如圖所示,線段樹有以下性質:
1.線段樹本質是棵二叉樹.
2.線段樹每個節點是代表一個區間l~r,而每個節點的兩個兒子是將父節點的區間一分為二,分別l~mid,mid+1~r。
3.葉子節點l等於r
綜上所述,我們可以按二叉樹的建樹方法,若節點編號為th,則節點的左兒子編號為th2,而右兒子記為th2+1。
這裡有個小技巧(算不上技巧的技巧)
#define lson th<<1 #define rson th<<1|1 //又是那句話,不是裝X,真的會快點的QWQ!!!
現有一個序列A1~N,要將線段樹構建以來維護,這裡我們用遞迴建樹
#define lson th<<1 #define rson th<<1|1 #define maxn 1000005 int a[maxn]; int tree[maxn*4];//手動畫一棵樹,發現是會達到4*n的級別的 void build(int l,int r,int th) { if(l==r)//當為葉子節點時 { tree[l]=a[l]; return; } int mid=(l+r)>>1; build(l,mid,lson);//構建左節點 build(mid+1,r,rson);//構建右節點 pushup(th);//從兩個子節點更新 }
上述類似於一個建樹的模板,根據我們的維護的物件的需要,我們可以將其進行擴充套件。
如維護最小值和最大值
#define lson th<<1 #define rson th<<1|1 #define maxn 1000005 int a[maxn]; int tree[maxn*4]; int mi[maxn*4]; int ma[maxn*4]; void pushup(int th) { mi[th]=min(mi[lson],mi[rson]); ma[th]=max(ma[lson],ma[rson]); //從兩個兒子進行更新 } void build(int l,int r,int th) { if(l==r)//當為葉子節點時 { tree[l]=mi[l]=ma[l]=a[l]; return; } int mid=(l+r)>>1; build(l,mid,lson);//構建左節點 build(mid+1,r,rson);//構建右節點 pushup(th);//從兩個子節點更新 }
今天晚上就先寫到這吧。
23:20
12.7