線段樹及空間開4倍

2021-07-17 01:54:48 字數 1890 閱讀 9467

下面我們來講解線段樹:

線段樹有許多應用,給出乙個序列,可以在任何乙個區間內找到最大,和最小值。可以求區間和等等等等。那麼應用就不多說了。畢竟能到這裡來的我相信都是為了a題,並且了解線段樹的吧!

廢話不多說了。

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

對於線段樹中的每乙個非葉子節點[a,b],它的左兒子表示的區間為[a,(a+b)/2],右兒子表示的區間為[(a+b)/2+1,b]。因此線段樹是平衡二叉樹,最後的子節點數目為n,即整個線段區間的長度。

下面我們來建樹:

void pushup(int rt)

void buildtree(int l,int r,int rt)

int mid=(l+r)>>1;

if(l<=mid)

if(r>mid)

pushup(rt);

return ;

}

下面我們就來貼出完整的**:

#include

#include

#include

using

namespace

std;

int n,t;

int array[100000

<<2];//100000乘4

void pushup(int rt)

void buildtree(int l,int r,int rt)

int mid=(l+r)>>1;

if(l<=mid)

if(r>mid)

pushup(rt);

return ;

}int query(int left,int right,int l,int r,int rt)

int mid=(l+r)>>1;

int res=0;

if(mid>=left)

if(mid1,r,rt<<1|1);

}return res;

}int main()}}

return

0;}

下面很多人就要問了,為什麼開陣列為什麼要開n*4的空間,好,我們來看看這張圖。

由圖可以很生動形象的看出,為什麼很多人開2*n會越界了。圖中的x是節點的總數。

但是我不想畫圖又怎麼辦呢?推公式??ok下面是我的乙個朋友推出來的公式!!!

假設n為節點的總數,no代表度為0的節點的總數。n2代表度為2的節點的總數!

由此可得:

倍數= n(max)/no -->no也相當於區間的長度。

n(max)可以看做是乙個滿二叉樹(最好的情況)。n(min)可以看做最後一層只有兩個子節點的樹(最壞的情況)。

|_k代表層數。

把n2消掉後可以得到。no = (n + 1) / 2

n(max)=2^k - 1

n(k-1層以上的節點總數)=2^(k-1) + 1

所以:no = [(2^(k-1)+1)+1]/2

倍數= n(max)/no

化簡可以得到 4- 5/(2^(k-2) + 1 )

-->4-5/(2^(k-1)+2)/2

-->4-5/no

即要開的空間倍數就是4-5/no

線段樹 4n 開四倍空間的原因

一 為何要使用線段樹?對於某一類問題,我們主要關注的是乙個線段或者區間。對於給定區間,更新區間中乙個元素或者乙個區間的值,查詢乙個區間 i,j 的最大值 最小值,或者區間數字和。線段樹不一定滿二叉樹,也不一定是完全二叉樹,但一定是平衡二叉樹,下面是線段樹元素個數n 2 k的情況,是滿二叉樹。下面是線...

線段樹為什麼要開四倍空間

最近在看 具體數學 這篇當做是乙個練習吧。假設我們用乙個陣列來頭輕腳重地儲存乙個線段樹,根節點是1,孩子節點分別是2n,2n 1,那麼,設線段長為l 即 1.l 1 設樹的高度為h,對h,有 h l 1,1 h l 2 l 1 l 1 這是乙個很簡單的遞迴式,並用公式3.11逐次代換,就等到h l ...

線段樹開4N空間證明

線段樹採用陣列儲存時,無疑,其儲存空間利用與其左右子樹定義有關 方式一 方式二 假設定義區間 1 5 的線段樹,很容易看出它們的不同 方式一 方式二 由此初步看來,採用第二種方式定義,可能會在其左邊產生較大的空白區域。實際上也的確如此,為了方便我們的習慣,考慮第一種方式定義情況 對於某一區間 l,r...