update-2018.07.23: 原文問題五思路描述有誤,已更正。
dfs序是樹在dfs先序遍歷時的序列,將樹形結構轉化成序列問題處理。
dfs有乙個很好的性質:一棵子樹所在的位置處於乙個連續區間中。
ps:deep[x]為x的深度,l[x]為dfs序中x的位置,r[x]為dfs序中x子樹的結束位置
1.點修改,子樹和查詢
在dfs序中,子樹處於乙個連續區間中。所以這題可以轉化為:點修改,區間查詢。用樹狀陣列或線段樹即可。
2.樹鏈修改,單點查詢
將一條樹鏈x,y上的所有點的權值加v。這個問題可以等價為:
1).x到根節點的鏈上所有節點權值加v。
2).y到根節點的鏈上所有節點權值加v。
3).lca(x,y)到根節點的鏈上所有節點權值和減v。
4).fa(lca(x,y))到根節點的鏈上所有節點權值和減v。
上面四個操作可以歸結為:節點x到根節點鏈上所有節點的權值加減v。修改節點x權值,當且僅當y是x的祖先節點時,x對y的值有貢獻。
所以節點y的權值可以轉化為節點y的子樹節點貢獻和。從貢獻和的角度想:這就是點修改,區間和查詢問題。
修改樹鏈x,y等價於add(l[x],v),add(l[y],v),add(l[lca(x,y)],-v),add(l[fa(lca(x,y))],-v)。
查詢:get_sum(r[x])-get_sum(l[x]-1)
用樹狀陣列或線段樹即可。
3.樹鏈修改,子樹和查詢
對於節點y其到根節點的權值和,考慮其子節點x的貢獻:w[x]*(deep[x]-deep[y]+1) = w[x]*(deep[x]+1)-w[x]*deep[y]
所以節點y的子樹和為:
ps:公式中的v[i]為手誤,應為w[i]。
所以用兩個樹狀陣列或線段樹即可:
第乙個維護∑w[i]*(deep[i]+1):支援操作單點修改,區間和查詢。(這也就是問題2)
第二個維護∑ w[i]:支援操作單點修改,區間查詢。(這其實也是問題2)
4.單點更新,樹鏈和查詢
樹鏈和查詢與樹鏈修改類似,樹鏈和(x,y)等於下面四個部分和相加:
1).x到根節點的鏈上所有節點權值加。
2).y到根節點的鏈上所有節點權值加。
3).lca(x,y)到根節點的鏈上所有節點權值和的-1倍。
4).fa(lca(x,y))到根節點的鏈上所有節點權值和的-1倍。
所以問題轉化為:查詢點x到根節點的鏈上的所有節點權值和。
修改節點x權值,當且僅當y是x的子孫節點時,x對y的值有貢獻。
差分字首和,y的權值等於dfs中[1,l[y]]的區間和。
單點修改:add(l[x],v),add(r[x]+1,-v);
5.子樹修改,單點查詢
修改節點x的子樹權值,在dfs序上就是區間修改,單點權值查詢就是單點查詢。
區間修改,單點查詢問題:樹狀陣列或線段樹即可;
6.子樹修改,子樹和查詢
題目等價與區間修改,區間查詢問題。用樹狀陣列或線段樹即可。
7.子樹修改,樹鏈查詢
樹鏈查詢同上,等價為根節點到y節點的鏈上所有節點和問題。
修改節點x的子樹權值,當且僅當y是x的子孫節點時(或y等於x),x對y的值有貢獻。
x對根節點到y節點的鏈上所有節點和的貢獻為:w[x]*(deep[y]-deep[x]+1)=w[x]*deep[y]-w[x]*(1-deep[x])
同問題三,用兩個樹狀陣列或線段樹即可。
七個經典演算法的研究
1 經典演算法研究系列 一 a 搜尋演算法 2 經典演算法研究系列 二 dijkstra 演算法 3 經典演算法研究系列 三 動態規劃演算法解微軟一道面試題 第56題 4 經典演算法研究系列 四 教你通透徹底理解 bfs和dfs優先搜尋演算法 5 經典演算法研究系列 五 紅黑樹演算法的實現與剖析 6...
七個基本量綱 七個基本量
長度 m長度是一維空間的度量。通常在量度二維空間中量度直線邊長時,稱呼長度數值較大 的為長,不比其值大或者在 側邊的為寬。所以寬度其實也是長度量度的一種,故此在三維 空間中量度 垂直長度 的高都是。共有公里 公引 公丈 公尺 公寸 厘公尺 公釐。奈米 nm1 1,000,000,000 公尺,微公尺...
七個笑話 頓悟七個人生道理
1 建築師 一位夫人打 給建築師,說每當火車經過時,她的睡床就會搖動。這簡直是無稽之談!建築師回答說,我來看看。建築師到達後,夫人建議他躺在床上,體會一下火車經過時的感覺。建築師剛 躺下,夫人的丈夫就回來了。他見此情形,便厲聲喝問 你躺在我妻子的床上幹什麼?建築師戰戰兢兢地回答 我說是在等火車,你會...