dfs序基本類型 詳細

參考

dfs序七個經典問題 ——weeping

本博文又名:手把手教你寫樹狀數組

1. 單點修改,子樹和查詢

單點修改,區間查詢

樹狀數組

維護每個點的權值:
1. 修改x (增加w ):單點修改——add(x,w);
2. 查詢x 的子樹:區間查詢——ans=query(le[x])-query(ri[x]-1);

2. 單點修改,樹鏈和查詢

首先將 uv 樹鏈和查詢轉化成 uroot,vroot,lca(u,v)root,fa(lca(u,v))root 的查詢,即要維護樹上節點到 root 的權值和。
考慮修改點 x ,影響到的即爲 x 的子樹內的點到 root 的權值,所以,單點修改事實上是區間修改
至於查詢,則是四個單點查詢

線段樹

維護每個節點到 root 的權值和:
1. 修改x (增加w ):區間修改——修改 [le[x],ri[x]] 區間,modify(1,le[x],ri[x],w);
2. 查詢[u,v] 鏈:單點查詢——查詢 u,v,lca(u,v),fa(lca(u,v))
ans=query(1,u)+query(1,v)-query(1,lca(u,v))-query(1,fa(lca(u,v)));
(本質上即四次查詢xquery(1, x);

樹狀數組

前綴和維護點到 root 的權值和的變化量:
1. 修改x (增加w ):區間修改——add(le[x],w),add(ri[x]+1,-w);
2. 查詢[u,v] 鏈:單點查詢——ans=[u,v]間權值和的初始值+query(le[u])+query(le[v])-query(le[lca(u,v)])-query(le[fa(lca(u,v))]);
(本質上即四次查詢xquery(x);

3. 樹鏈修改,單點查詢

樹鏈修改的道理同上,等價於修改某個點到 root 的路徑的權值和。
考慮修改的樹鏈的一個端點爲 x ,增加值爲 w ,影響到的則是 xroot 的路徑上的點的權值,即當且僅當 xy 的子樹內,修改 x 會對 y 的權值造成影響,增加值爲 w
對於點 y 而言,其權值的變化量事實上就是其子樹中點權值的變化量之和(相當於把 y 的變化量記在了其子孫節點的頭上),即xyw[x] ,故爲區間查詢。而維護的即爲子樹中點權值的變化量,即單點修改

樹狀數組

維護每個點權值的變化量:
1. 修改[u,v] 鏈(增加w ):單點修改——add(u,w),add(v,w),add(lca(u,v),-w),add(fa(lca(u,v)),-w);
(本質上即四次修改xadd(x,w);
2. 查詢x :區間查詢——ans=x的初始值+query(ri[x])-query(le[x]-1);

4. 樹鏈修改,子樹和查詢

樹鏈修改的道理同上,等價於修改某個點到 root 的路徑的權值和。
考慮修改的樹鏈的一個端點爲 x ,影響到的則是 xroot 的路徑上的點的權值,即當且僅當 xy 的子樹內,修改 x 會對 y 的子樹和造成影響,增加值爲 w[x](depth[x]depth[y]+1)
y 的變化量總和則爲

xyw[x](depth[x]depth[y]+1)=xyw[x](depth[x]+1)depth[y]xyw[x]

仍是單點修改,區間查詢

樹狀數組

開兩個樹狀數組,分別維護 w[x](depth[x]+1)w[x] .
1. 修改[u,v] 鏈(增加w ):單點修改——
add1(u,w*(depth[u]+1)),add1(v,w*(depth[v]+1)),add1(lca(u,v),-w*(depth[lca(u,v)]+1)),add1(fa(lca(u,v)),-w*(depth[fa(lca(u,v)]+1);
add2(u,w),add2(v,w),add2(lca(u,v),-w),add2(fa(lca(u,v)),-w);
(本質上即八次修改xadd(x,w);
2. 查詢x 的子樹:區間查詢——
ans=子樹和的初始值+query1(ri[x])-query1(le[x]-1)-depth[x]*(query2(ri[x])-query2(le[x]-1));

5. 子樹修改,單點查詢

區間修改,單點查詢

樹狀數組

前綴和維護點權值的變化量:
1. 修改x 的子樹(增加w ):區間修改——add(le[x],w),add(ri[x]+1,-w);
2. 查詢x :單點查詢——ans=x的初始值+query(le[x]);

6. 子樹修改,子樹和查詢

區間修改,區間查詢

線段樹

維護每個點的權值
1. 修改x 的子樹(增加w ):區間修改——add(1,le[x],ri[x],w);
2. 查詢x 的子樹:區間查詢——ans=query(1,le[x],ri[x]);

樹狀數組

具體見【小結】樹狀數組的區間修改與區間查詢 ——MoeO3,本菜就不多廢話了_(:3」∠)_
(已經赤果果地變成一篇樹狀數組的文章啦(逃

7. 子樹修改,樹鏈和查詢

樹鏈修改的道理同2. 3. 4. ,等價於修改某個點到 root 的路徑的權值和。
考慮修改 x 的子樹,影響的則是 x 的子樹內的點到 root 的路徑的權值和,即當且僅當 yx 的子樹內,修改會對 y 的查詢造成影響,增加值爲 w[x](depth[y]depth[x]+1) 。故爲區間修改,單點查詢

樹狀數組

開兩個樹狀數組,分別維護 w[x](depth[x]+1)w[x] .
1. 修改x 的子樹(增加w ):區間修改——
add1(le[x],w[x]*(-depth[x]+1);add1(ri[x]+1,-w[x]*(-depth[x]+1);
add2(le[x],w[x]);add2(ri[x]+1,-w[x]);
2. 查詢[u,v] 鏈:單點查詢——
ans=[u,v]間權值和的初始值+(query1(le[u])+query1(le[v])-query1(le[lca(u,v)])-query1(le[fa(lca(u,v))]))+depth[y]*(query2(le[u])+query2(le[v])-query2(le[lca(u,v)])-query2(le[fa(lca(u,v))]));
(本質上即八次查詢xquery(x)

完結撒花~
哪裏有錯誤還煩請批評指正啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章