1. 程式人生 > 其它 >【題解】Ynoi2010 Brodal queue

【題解】Ynoi2010 Brodal queue

本題不弱於小 Z 的襪子,考慮分塊,令 \(B\) 為塊數。

先考慮單點修改,可以令 \(f(x,y)\) 表示從塊 \(x\) 中選出一個數,然後從塊 \(y\) 中選出同樣的數的方案數,放到平面上,有值的地方就是一個三角形,詢問也是詢問一個三角形中的 \(f(x,y)\) 和。

怎麼做修改,對每個顏色維護一個前綴出現次數和,然後就可以快速計算貢獻了。注意到如果修改的點屬於塊 \(x\),影響的 \(f(x,y)\) 是呈 "L" 狀,且拐點一定頂到 \(y=x\) 這條線。所以修改能拆成 "一行 + 拐點 + 一列" 的形式,拐點單獨維護(即同一塊內的貢獻),行和列分開維護,做字首和,詢問的時候分別查詢行和列即可。

此時取塊大小 \(B=\sqrt{n}\),時間複雜度為 \(O(n\sqrt{n})\)

接下來考慮做原問題,即將單點修改變成區間染色。區間染色的常用套路是顏色段均攤。考慮在每個塊內壓縮所有的顏色段,表示成若干數對 \((c,t)\) 的形式(\(c\) 指顏色編號,\(t\) 指顏色段長度),同樣討論修改:

  • 散塊:暴力重構,將區間覆蓋後可能消失的段刪除貢獻,然後暴力做區間覆蓋重建顏色段結構,再考慮原來刪除貢獻的位置對應的新段的貢獻。這裡細節有點多。

    不難發現等價於普通序列上的顏色段均攤,暴力刪除 / 重建的段數是 \(O(\frac{n}{B}+m)\) 的(注意到對散塊的修改總量是 \(O(m)\)

    的)。同時刪除 / 加入段後更新 \(f(x,y)\) 的方法和單點修改部分沒有區別,單次修改仍然為 \(O(B)\)

  • 整塊:區間染色時跨過的整塊不可能每次暴力更新 \(f(x,y)\),不過可以注意到此時整段都是一個顏色。不妨在整塊被染成同一顏色時(之前仍然有若干顏色段),暴力刪除之前的所有顏色段的貢獻,並且在查詢的時候單獨處理整塊。

    注意到整塊染色,刪除之前所有顏色段這一操作仍然可以套用顏色段均攤的複雜度分析方法。同時詢問暴力計算整塊的貢獻,和暴力計算散點的貢獻幾乎沒有區別,可以輕鬆算出。

仍然考慮取 \(B=\sqrt{n}\)(當然可以因常數原因微調),時間複雜度為 \(O((n+m)\sqrt{n})\)

看起來我是 sb,對拍的時候一定要多調調塊大小啊 >_<

程式碼:記錄詳情 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)