1. 程式人生 > >資料結構的半夜----線段樹學習筆記1

資料結構的半夜----線段樹學習筆記1

蒟蒻奉上一篇線段樹學習筆記(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