[學習筆記]線段樹分治


https://www.luogu.org/blog/Miracevin/shuo-ju-jie-gou

一種離線處理方法

可以處理“具體哪個修改對詢問有影響”、可以貢獻不獨立、可以支持插入刪除

關鍵是把一個修改看成一個區間,每個詢問是一個葉子,修改在線段樹上打標記

例題6:

例題 7
• 給出一張圖
• 對每個點求出強制這個點點度為 1 的最小生成樹的權值

• 𝑛 ≤ 100000, 𝑚 ≤ 300000

等價於:每個邊存在三段:[1,x-1],[x+1,y-1][y+1,n]

LCT維護最小生成樹

i的答案再加上和i相鄰的邊權最小值

 

例題 8
• 給一棵樹,邊有邊權
• 每次操作是刪除一條邊並加入一條邊,保證操作完還是樹
• 你需要維護有多少點對 𝑥, 𝑦 的路徑上所有數的最大公約數是 1
• 𝑛 ≤ 100000, 𝑎𝑖 ≤ 100000, 𝑚 ≤ 30000

gcd這個東西太難搞。

反演一下得到:

ans=∑miu(d)f(d)

f(d)表示路徑上的點都是d的倍數的點對的個數

也就是,所有是d的倍數的點構成的若干個聯通塊,f(d)=∑szi*(szi-1)/2

 

考慮對每個邊出現的區間進行線段樹分治

然后dfs,用按秩合並並查集維護每個d的f(d),也就是維護好聯通塊∑szi*(szi-1)/2

每加入一個邊,枚舉這個邊兩邊的點的gcd的約數d,再對每個並查集進行維護。

棧序撤銷

總共每個邊只會出現sqrt(w)次,w是邊權,也即gcd(x,y)

(當然LCT也可以,常數爆炸就是了)

 

例題 9
• (CTSC2016時空旅行)
• 你需要維護若干個版本的集合,每個集合元素是 𝑥, 𝑣
• 每次可以擴展一個版本,擴展內容為加一個新元素或刪除一個已
有元素
• 每次詢問一個 𝑦,要你在給定版本 𝑖 的集合中找出 𝑥, 𝑣 使得
𝑥 − 𝑦 2 + 𝑣 最小
• 𝑛, 𝑚 ≤ 1000000

[CTSC2016]時空旅行

也比較神仙

先推性質咯

 

發現版本擴展這個東西是一個樹形結構

每個元素存在的區間,直接按照版本分的話,可以分層O(m),直接掛掉

於是考慮用dfn序!,x一定出現在x的子樹里,並且刪掉x這個元素操作,可以把這個區間再分成若干小區間(扣除小子樹)

但是總區間數是m

為線段樹分治打下基礎

 

最優化的式子明顯是斜率優化,維護下凸殼,橫坐標是x,縱坐標是x*x+v,斜率是2y

考慮怎么處理詢問:

1.dfs?不支持單點增量,只能平衡樹暴力維護凸包。。。。復雜度不敢想象。

2.考慮每個修改區間對葉子詢問的影響。(畢竟可以直接取min)

既然已經離線,我們可以排序!把修改按照x排序,詢問按照斜率k排序,按照順序加入線段樹,

這樣,每個線段樹的點維護一個vector(其實是單調隊列),就是這個區間的凸包,x遞增,所以單點增量即可

再維護一個vector,每個詢問插入的時候,k從小到大,再加入這個vector里面。然后單調隊列即可。

3.考慮對每個詢問,找父鏈上的凸包來更新答案

只用凸包的一個vector即可。

詢問k從小到大,每次找整個鏈上的凸包做一下。每個區間可以單調隊列處理。

(這題橫坐標有相同的,要注意)

 

 


upda:2019.5.17

線段樹分治套虛樹?

詢問區間放上去,關鍵點放上去,建立虛樹再DP

O(nlog^2)

【2018 12月集訓 Day2】小奇的危機

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM