多校 A 層衝刺 NOIP2024 模擬賽 17

Qyun發表於2024-11-02

多校A層衝刺NOIP2024模擬賽17

T1 網格

簽到題

注意到 \(+\)\(\times\) 由於優先順序其實是分開的,所以可以考慮每到達一個 \(+\) 計算一次貢獻(乘上一個組合數),然後將前置貢獻重新賦值為方案數,DP 只需考慮連續 \(\times\) 段即可。

時間複雜度 \(O(nm)\)

T2 矩形

根號分治

發現不管怎麼列舉總會出現一些特殊情況使得複雜度存在瓶頸,並且雖然值域是 \([1,n]\) 但總共只有 \(O(n)\) 個點,圖是很稀疏的。

這啟發我們把特殊的拿出來分討去做,考慮以列為單位,並設定閾值 \(B\),一列中點數大於 B 的記為大段,小於的記為小段,則只需要考慮 \(3\) 種情況的貢獻。

  • 大段與小段之間的貢獻
    注意到大段的個數不會超過 \(O(\frac{n}{B})\) 個,考慮列舉每一個大段,然後去計算所有小段對它的貢獻。具體的當列舉到一個大段時,在值域上標記它所擁有的點,然後列舉小段,查詢每個有多少個相同縱座標,記為 tot,則一個小段的貢獻為 \(\binom{tot}{2}\)
    這一部分的時間複雜度為 \(O(\frac{n^2}{B})\)

  • 大段與大段之間的貢獻
    有兩種做法
    第一種同上即可解決。
    第二種可以使用 \(bitset\) 最佳化,具體的列舉任意兩個,然後用 \(bitset\) 按位與計算相同個數,然後同上組合數計算貢獻,時間複雜度為 \(O(B^2\frac{n}{w})\)

  • 小段與小段之間的貢獻
    注意到小段只有至多 \(O(B)\) 個元素,可以考慮每個點列舉 \(O(B)\) 次去做。
    具體的,可以在值域上列舉下端點,然後對於所有包含這個點的段進行計算,即將所有在下端點上方的點加入到值域 \(cnt\) 陣列中,由於欽定了下端點,所以 \(cnt\) 中直接就是答案。
    考慮時間複雜度,發現每個點至多會被列舉 \(O(B)\),而總共有 \(O(n)\) 個點,這一部分的時間複雜度為 \(O(nB)\) 的。

\(B\)\(\sqrt n\) 時總複雜度最優,為 \(O(n\sqrt n)\),由於本題特殊資料很難造,並且就算強度高也遠遠達不到這個上界所以跑的飛快。

雙倍經驗 [Ynoi Easy Round 2024] TEST_132

T3 集合

不會

T4 倒水

機率期望,資料結構最佳化DP,線段樹

注意到一個性質

只要有一次向前倒就結束了,證明顯然。

那麼有一個推論

\(b_i\)\(i\) 當前的量,\(i\) 倒出去的水的量為 \(\min(a_j,b_i)\),證明考慮分討,當 \(j\) 中沒有水時顯然,而有水時 \(i\) 中的水一定是從 \(j\) 中來的,所以一定達不到 \(j\) 的上界。

那麼可以設計狀態進行 DP,設 \(f_{i,j}\) 表示當到 \(i\) 要倒水時 \(i\)\(j\) 單位體積的水的機率。

根據上述結論,發現向前轉移能直接計算貢獻即可,而向後轉移則轉移到 \(f_{k,\min(a_k,j)}\)(此時仍需計算自己的貢獻)。

現在就得到一個 \(O(n^3)\) 的做法。

顯然能字首和最佳化,將刷表改為填表,等轉移完後再計算貢獻即可最佳化至 \(O(n^2)\),這一部分比較重要,下面具體講講。

設輔助陣列 \(s1_{i,j}=\sum_{a\le i,b\le j}f_{a,b},s2_{i,j}=\sum_{a\le i,b\le j}bf_{a,b},hs_i=\sum_{1\le j\le n}\max(0,i-a_j)\),即 \(s1,s2\) 分別是機率、期望的字首和。

  • 轉移

\[\begin{cases} f_{i,j}=(s1_{i-1,j}-s1_{i-1,j-1})\frac{1}{n-1}\quad &j< a_i \\ f_{i,j}=(s1_{i-1,n}-s1_{i-1,j-1})\frac{1}{n-1}\quad &j=a_i \end{cases} \]

  • 計算貢獻
    \(res_i\) 表示 \(i\) 的期望(答案),下面為了方便就直接寫等號了,實際上為兩部分之和。

    • 向前倒以及向後倒剩下的

      \(res_i=\sum_{j=1}^{a_i} hs_jf_{i,j}\frac{1}{n-1}\)

    • 別的向前倒,倒給它的

      \(\min\) 去掉,所以得分討。

      • 從大於 \(a_i\) 倒來

        \(res_i=(s1_{n,n}-s1_{i,n}-s1_{n,a_i}+s1_{i,a_i})a_i\frac{1}{n-1}\)

      • 從小於 \(a_i\) 倒來

        \(res_i=(s2_{n,a_i}-s2_{i,a_i})\frac{1}{n-1}\)

\(O(n^2)\) 比較平凡。

考慮最佳化

只需考慮 \(O(n^2)\) 的瓶頸部分。

即求解 \(hs,s1,s2\) 陣列,以及(用 \(hs\) 陣列)計算倒剩下的貢獻。

對於求解 \(hs\) 陣列可以對 \(a\) 陣列排序後求解,就將這一部分複雜度降低到 \(O(nlogn)\)

如果只維護高度值域的字首和(即 \(s_{i,j}=\sum_{k\le j}f_{i,k}\) )會發現一些很好的性質!

\[\begin{aligned} &\begin{cases} f_{i,j}=\frac{1}{n-1}s_{i-1,j}\quad &j< a_i \\ f_{i,j}=\frac{1}{n-1}\sum_{k\ge j}s_{i-1,k}\quad &j=a_i \end{cases} \\ &\begin{cases} s_{i,j}=(1+\frac{1}{n-1})s_{i-1,j}\quad &j< a_i \\ s_{i,j}=s_{i-1,j}+\frac{1}{n-1}f_{i,j}\quad &j=a_i \end{cases} \end{aligned} \]

如果用線段樹去維護值域的話( 掃描線 )則 \(j< a_i\) 在只需要區間乘即可,而 \(j=a_i\) 則需區間求和,單調修改。

考慮怎麼計算貢獻

  • \(hs\)

    \(hs_i\) 作為係數放線上段樹上,掃描到 \(i\) 時區間求和即可。

  • \(s1\)

    發現只有 \(4\) 個值 ( 矩形面積 ) ,按第一維處理,掃描到 \(i\) 時處理一次( 掃描線的套路 ),掃描結束處理一次。

  • \(s2\)

    只需結合一下 \(hs,s1\) 的做法即可,即線上段樹上每一個位置,將位置作為係數,然後掃描線求矩形面積。

這樣就只需要維護一個支援區間乘法,單點修改,區間求和的線段樹即可。

時間複雜度 \(O(nlogn)\),常數很小,能輕鬆爆標。

p

相關文章