日常 線段樹空間

2022-07-30 04:15:16 字數 2455 閱讀 4548

線段樹空間到底該開多大?**載自luogu @小粉兔)

這裡的線段樹指的是,每個節點都有00或22個孩子的二叉樹。

編號為xx的節點的左孩子(如果存在的話)的編號為2x2x,右孩子的編號為2x+12x+1。而根節點的編號一般為11。

一棵擁有xx個葉子節點的線段樹被稱為xx-線段樹。

除此之外,一棵xx-線段樹(x>1)(x>1)還需要滿足其左子樹為一棵\lfloor x/2\rfloor⌊x/2⌋-線段樹,其右子樹為一棵\lceil x/2\rceil⌈x/2⌉-線段樹。

有上述條件可以唯一確定一棵xx-線段樹(x>0)(x>0)的形態。

接下來要**的是:一棵nn-線段樹的節點中的最大的編號id_idmax​,與nn有什麼關係。因為最大的編號和在程式中實現時所用的陣列大小以及使用的記憶體大小有密切的聯絡。

有人認為id_idmax​小於4n4n,有人認為id_idmax​不會超過5n5n。有人提出可以證明id_\leq 3n+1idmax​≤3n+1。

真相到底是什麼?

11-線段樹高度為11。

22-線段樹高度為22。

3,43,4-線段樹高度均為33。

5\sim 85∼8-線段樹高度均為44。

9\sim 169∼16-線段樹高度均為55。

可以看出,一棵xx-線段樹的高度為\lceil \log_2x\rceil +1⌈log2​x⌉+1或等於\lceil \log_2 2x\rceil⌈log2​2x⌉。

根據此,結合二叉樹的簡單性質,我們可以得到乙個線段樹id_idmax​的比較松的上估計:id_\leq 2^-1< 4n-1\leq 4n-2idmax​≤2⌈log2​2x⌉−1<4n−1≤4n−2。證實了id_idmax​小於4n4n的斷言。

而觀察線段樹的形態可以得出另乙個結論:一棵線段樹除了最後一層,其他層都是滿的。

據此,有人提出了另乙個聲稱更緊的估計:2^+n-12⌈log2​x⌉+n−1。並據此計算得出id_\leq 3n+1idmax​≤3n+1的結論。然而這是錯誤的。因為這個估計依賴於乙個錯誤的假設:線段樹最後一層的節點是靠左連續的,或稱「完全二叉樹」的形態。

實際上,在n=36n=36時,nn-線段樹的id_idmax​就等於113>3n+1113>3n+1。這是不滿足估計的最小的nn。

那麼什麼界才是精確的呢?線段樹的陣列到底要開多大呢?

只要知道了nn-線段樹的nn值,就能確定線段樹的形態。只要知道了線段樹的根節點編號,就能確定線段樹的id_idmax​是多少。

那麼任何快速地計算id_idmax​呢?考慮以下演算法:

若線段樹為11-線段樹,那麼其id_idmax​為根節點編號。

若線段樹為xx-線段樹(x>1,x\equiv 0(mod\;2))(x>1,x≡0(mod2)),且根節點編號為yy,那麼其id_idmax​為根節點編號為2y+12y+1的x/2x/2-線段樹的id_idmax​。

若線段樹為xx-線段樹(x>1,x\equiv 1(mod\;2))(x>1,x≡1(mod2)),根節點編號為yy,且(x+1)/2(x+1)/2-線段樹的深度等於(x-1)/2(x−1)/2-線段樹的深度,那麼其id_idmax​為根節點編號為2y+12y+1的(x-1)/2(x−1)/2-線段樹的id_idmax​。

若線段樹為xx-線段樹(x>1,x\equiv 1(mod\;2))(x>1,x≡1(mod2)),根節點編號為yy,且(x+1)/2(x+1)/2-線段樹的深度不等於(x-1)/2(x−1)/2-線段樹的深度,那麼其id_idmax​為根節點編號為2y2y的(x+1)/2(x+1)/2-線段樹的id_idmax​。

不難證明上述演算法可以在\theta(\log_2 n)θ(log2​n)的時間複雜度內計算出正確的結果。

這是乙個可接受的演算法,接下來我用 c++ 語言實現了計算id_idmax​的函式,並用它計算了nn與id_idmax​的關係:

1 #include2

int dep[100000001];3

int max(int i,int j)

4void

init()

9int getnum(int rootnum,int

size)

16int

main()

25 printf("

%.15lf\n

",max);

26return0;

27 }

輸出的結果是3.992197027439024,這意味著在1000000(10^6)1000000(106)內,id_idmax​最大能達到3.992\cdots3.992⋯倍的nn那麼大。這的確不超出我們的預期。

所以結論是什麼?線段樹的陣列到底要開多大?

結論就是:線段樹開44倍總沒錯。你也可以算出乙個nn-線段樹(n\leq k\times 10^5)(n≤k×105)的id_idmax​最大能到多少。更簡單且記憶體占用不大的方法是算出第乙個比2n2n大的22的次冪,並把陣列開到那麼大。

線段樹及空間開4倍

下面我們來講解線段樹 線段樹有許多應用,給出乙個序列,可以在任何乙個區間內找到最大,和最小值。可以求區間和等等等等。那麼應用就不多說了。畢竟能到這裡來的我相信都是為了a題,並且了解線段樹的吧!廢話不多說了。線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中...

日常摸魚 bzoj4358 莫隊 線段樹

題意 給出乙個長度為 n 的排列 p p 1,p 2,p n 以及 m 個詢問。每次詢問某個區間 l,r 中,最長的值域 連續段長度 例如 n,m leq 5 times 10 4 題解 這題網上有挺多做法的,莫隊 線段樹 莫隊 並查集 莫隊 棧 kd tree,這裡我原本是想找kd tree的題才...

hdu 6183 線段樹的空間優化

題意 乙個空的座標系,有 種操作 1 x y c表示在 x,y 點染上顏色c 2 x y1 y2表示查詢在 1,y1 到 x,y2 範圍內有多少種不同的顏色 0表示清屏 3表示程式退出 0 x,y 1000000,0 c 50 思路 開五十個線段樹 一種顏色乙個 以y為下表,儲存min x,因為查詢...