1. 程式人生 > >線段樹合並淺談

線段樹合並淺談

-o 希望 day count 代碼 cpp 簡單 講解 spa

對於某些對子樹的統計問題,我們固然可以用DSU on Tree來解決,但是一旦帶上修改,甚至是加上歷史化版本的查詢,我們就不得不求助於其他的算法,本篇將對線段樹合並進行講解


線段樹合並一般用於對子樹的統計,一般的套路就是對樹的每一個節點都開上一顆動態開點線段樹,然後統計子樹信息時,合並所有兒子信息,統計答案,然後繼續向上走;

例題也很多,比如[USACO17JAN]Promotion Counting晉升者計數,【NOIP2016 DAY1】天天愛跑步等等都可以這樣亂搞,實現起來也非常好理解,這是針對天天愛跑步類型(權值線段樹)的\(Merge\)代碼:

\(code\):

void merge(int &x,int y)
{
    if(!x||!y){x=x+y;return;}
    sum[x]+=sum[y];
    merge(ls[x],ls[y]);
    merge(rs[x],rs[y]);
}

如果希望改為維護歷史版本,可以這樣改:

int merge(int x,int y)
{
    if(!x||!y){ return x+y;return;}
    int p=++tot;
    ls[p]=merge(ls[x],ls[y]);
    rs[p]=merge(rs[x],rs[y]);
    sum[p]=sum[ls[p]]+sum[rs[p]]
    return p;
}

簡單好寫,易於理解

線段樹合並淺談