題解 LOJ2719 NOI2018 氣泡排序

2022-03-12 12:53:13 字數 1382 閱讀 8448

考慮乙個排列的交換次數何時會超過下界。以題目中的\(3\ 2\ 1\)為例,在把\(3\)向後移時\(2\)被向前推了一次,在把\(1\)向前移時\(2\)又被向後推了一次。這樣一來一回,就產生了無效操作。於是我們發現,乙個排列是好的,當且僅當在氣泡排序的過程中,不存在某個元素同時做了兩個方向的移動(這樣必然產生「一來一回」的情況)。

嘗試把這個觀察具體化一些。考慮乙個位置\(i\),如果它前面存在乙個\(>p_i\)的數,後面存在乙個\(的數。則在氣泡排序的過程中,\(p_i\)必定是先被向後挪了一次,又被向前挪了一次(當然,也可能是先向前再向後)。也就是說,在這種情況下,\(p_i\)一定是同時做出了兩個方向的移動。根據前面的討論,此時這個排列\(p\)氣泡排序的交換次數,必然超過了下界\(\frac\sum|i-p_i|\)。打表可以驗證,除了這種情況以外,其他的排列都能取到這個下界。於是我們得出結論:乙個排列是「好」的,當且僅當它不存在乙個長度\(\geq3\)的下降子串行,或者說最長下降子串行的長度\(<3\)。

繼續分析這個結論的特殊性質。考慮現在我們逐位構造乙個「好」的排列,現在填到位置\(i\),前\(i-1\)位的最大值為\(mx\)。則第\(i\)位要麼填任意乙個\(>mx\)的數,要麼填\(的最小的數(否則就一定會出現長度為\(3\)的下降子串行)。於是想到dp。設\(dp[i][j]\)表示考慮了前\(i\)位,最大值是\(j\)時,第\(i+1\)到第\(n\)位的填數方案。這樣我們可以從後往前轉移,即得到:

\[dp[i][j]=\left(\sum_^dp[i+1][k]\right)+dp[i+1][j]=\sum_^dp[i+1][k]

\]為什麼要把dp陣列定義成「第\(i\)位之後的填數方案」呢?因為這樣便於我們處理字典序的問題。我們統計答案時,列舉從第\(i\)位開始,字典序第一次大於輸入的排列\(q\)(前\(i-1\)位全部和\(q\)相等)。我們設\(mx_i=\max_^q_j\),則:

\[ans_i=\sum_^dp[i][j]=dp[i-1][mx_i+1]

\]答案就是所有\(ans_i\)之和。

這樣暴力dp是\(o(n^3)\)的,用字尾和優化可做到\(o(n^2)\)。

把\(dp[i][j]\)視作從二維平面直角座標系上乙個點\((i,j)\)走到\((n,n)\)的方案數。每步必須向右走一格,同時可以向上走若干格或不向上走。但走的過程中,必須始終保證\(i\leq j\)。考慮用總方案減去不合法的(\(i>j\))的方案。

綜上,可知\(dp[i][j]=-\)。

按之前的方法,直接統計答案即可。

注意,如果\(q\)的前\(i\)位已經存在不合法的情況(不符合「第\(i\)位要麼填乙個\(>mx_\)的數,要麼填\(的最小的數」這條規則),要及時break

時間複雜度\(o(n)\)。

參考**

loj 2719 NOI2018 氣泡排序

t 5,sum n le 2000000 考慮什麼樣的排列是好的.為了達到下界,p i 應該只向 i 的方向移動,也就是說,不存在乙個數左右都有逆序對,也就是說,不存在 a使得 p a p b p c 無視 q 的限制,可以用dp計算答案,設 dp i,j 表示確定了排列的前 i 個數,設其中最大值...

loj 2721 NOI2018 屠龍勇士

有 n 條惡龍,每條惡龍有乙個初始生命值 a i 恢復力 p i 擊殺後會掉落一把劍.初始你有 m 把劍.給出每把劍的攻擊力.現在你打算按照以下方法殺掉所有惡龍 問最小的 x 如果不存在能殺掉所有惡龍的 x 輸出 1 有 t 組資料 n le 10 5,m le 10 5,t le 5,a i le...

NOI2018 歸程 題解

容易發現,當水位線確定了,圖會被分成若干個連通塊,連通塊裡的點可以互相到達,故連通塊內點的答案為其中的點到 1 的距離的最小值,這個可以先 dijkstra 預處理求出 spfa 死了 那考慮怎麼維護連通塊。可持久化並查集?感覺不好搞,有一種神奇的演算法 kruscal 重構樹。其實就是 krusc...