線段樹合並淺談
阿新 • • 發佈:2018-10-27
-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;
}
簡單好寫,易於理解
線段樹合並淺談