dfs序七個經典問題

2022-05-05 06:00:12 字數 1791 閱讀 4373

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 建築師 一位夫人打 給建築師,說每當火車經過時,她的睡床就會搖動。這簡直是無稽之談!建築師回答說,我來看看。建築師到達後,夫人建議他躺在床上,體會一下火車經過時的感覺。建築師剛 躺下,夫人的丈夫就回來了。他見此情形,便厲聲喝問 你躺在我妻子的床上幹什麼?建築師戰戰兢兢地回答 我說是在等火車,你會...