題解 LOJ3278 「JOISC 2020 Day3」收獲


感謝 myt 神仙教會了我樹狀數組!Orz!

果樹和人是相對運動的,因為是對人做詢問,所以可以考慮讓人不動,果樹運動。這樣的好處是可以把人的結構固定下來,便於用數據結構維護。

具體來講,對於所有\(i\in[1,n]\),我們從第\(i\)個人向逆時針方向第一個到他的距離\(\geq C\)的人\(j\)連邊。表示某棵果樹被\(i\)摘掉后,下一個摘的人是\(j\)。邊權是這兩次采摘的時間間隔。

對於每棵果樹,向它逆時針方向的第一個人連邊。表示它的果子第一次是被這個人摘到的。邊權是這個人到這棵果樹的距離。

因為每個點都有且僅有一條出邊,於是,我們得到了一個基環內向樹森林。其中,每棵果樹是一個葉子,其他節點都是人。開始時,果樹會從它所在的葉子出發,經過每條邊需要一定的時間。我們要回答\(Q\)次詢問,問在某一時刻之前某個節點共被果樹經過了多少次(同一棵果樹如果多次經過同一節點,則每次都要被算在答案里)。

先把詢問離線下來。給每個節點開一個vector,存關於這個節點的詢問。

基環樹森林里的每棵基環樹顯然相互獨立。我們對分別對每棵基環樹計算答案。

對於一棵基環樹,我們先斷掉它環上的一條邊。然后分兩種情況討論:

  • 果樹到達被詢問節點時,之前沒有經過被斷掉的這條邊。
  • 果樹到達被詢問節點時,之前經過了被斷掉的這條邊。注意,因為是在環上,所以有可能多次經過。

對於第一種情況,答案顯然是樹上(基環樹斷掉一條邊后會變成普通的樹)某個子樹內,深度不超過某個值的果樹數量。用dfs序把“子樹”轉化成一段區間,問題變為簡單的二維數點問題。具體來說,我們把所有的果樹和詢問放在一起,按深度排序。每次加入一個點,或詢問一個區間內的點數。可以用樹狀數組維護。

對於第二種情況。我們先把每棵果樹移動到被斷掉的這條邊的終點。對於第\(i\)棵果樹,設它移動到這個點所花費的時間為\(t_i\)。設要回答的詢問時間為\(T\)。則對答案的貢獻是\(\sum_{t_i\leq T}\frac{T-t_i}{len}\)。其中\(len\)是基環樹的環長。這里的除法取整是一個細節。如果余數大於等於被斷掉的邊的終點被詢問的節點的距離,則上取整,否則下去整。設這個距離為\(d\),則我們也可以形式化地把這個式子寫作:\(\sum_{t_i\leq T}\lfloor\frac{T-t_i+len-d}{len}\rfloor\)

其實這也是一個二維數點問題。先把果樹和詢問一起按時間排序。我們可以用兩個變量\(num,sum\),分別記錄已經掃描到的果樹的數量,和果樹的\(\lfloor\frac{t_i}{len}\rfloor\)之和。對於某個查詢\(x=T+len-d\),先令答案等於\(\lfloor\frac{x}{len}\rfloor\cdot num-sum\)。這樣會多計算的是\(t_i\bmod len\)大於\(x\bmod len\)的這些果樹(每棵這樣的果樹會使答案被多算\(1\))。我們事先把所有余數離散化一下,然后在樹狀數組上做單點修改、后綴和查詢即可。

時間復雜度\(O(n\log n)\)

參考代碼


免責聲明!

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



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