1. 程式人生 > >線段樹合併複雜度證明

線段樹合併複雜度證明

前言

近期對線段樹合併有了更深的瞭解,所以在這裡寫一下一些自己的想法

適用問題

線段樹合併有一類經典的模板,現在對於一棵有n個葉子節點的樹(Tip:對於一棵N個節點的樹,其葉子節點數量小於等於 N 2 \lceil \frac N2 \rceil

),每個葉子節點上都有一個值域為m的值線上段樹中,一個非葉子節點節點的線段樹由所有子節點的線段樹合併而成,求相關的資訊

程式碼

inline node*merge(node*x,node*y)//node為線段樹節點的結構體名稱
{
    if(x==NULL)return y;//NULL說明該指標為空
    if(y==NULL)return x;
    x->lson=merge(x->lson,y->lson);
    x->rson=merge(x->rson,y->rson);
    return x;
}

複雜度

對於整棵樹,做完的複雜度為 O ( n l o g m + N

) O(nlogm+N)
證明:
由於要遍歷整棵樹,所以有至少的O(N)的複雜度
對於一個葉子節點,其構樹的複雜度為 O ( l o g m ) O(logm) 。容易發現,兩棵線段樹合併時,由於如果一棵線段樹為空就不做,只有兩顆線段樹都有值時往下,所以往下dfs的終止節點一定是兩棵線段樹節點的lca。對於一個節點,做完其子樹的線段樹合併的複雜度為 i l c a d e p t h [ i ] \sum_{i為線段樹上兩個葉子節點的lca}depth[i]
(Tip:由於對於兩條路徑可能會有相交之處,所以這個複雜度是上界,實際上這部分是不滿的)
每有一個滿足條件的lca,說明有兩個值合併在一起了,合併次數為N-1次,而深度是 O ( l o g m ) O(logm) 的,所以總複雜度為O(nlogm+N)
證畢

例題

「PKUWC2018」Minimax

總結

這是一個很妙的模型,乍一眼複雜度不容易得出,而且比較好寫,值得記住