P9753 [CSP-S 2023] 消消樂
這題想到了 50pts,想不出來怎麼最佳化了。
50pts:考慮列舉子串左端點,模擬操作過程,直接用棧模擬,遇到相同的則刪去,如果某個時刻棧為空,那麼合法子串數加一。
考場上只想到為空的時候可消除,下面的性質才是關鍵的。因為我們列舉左端點,每次只判斷了 \([l,r]\) 的可消除子串,這樣子無論如何都要 \(O(n^2)\)。所以我們需要考慮如何在列舉左端點的同時找到其他左端點的可消除子串。
棧的過程其實啟發我們:對於兩個時刻 \(l\) 和 \(r\),如果兩個時刻棧是一樣的,那麼說明 \([l+1,r]\) 是可消除的。
所以我們如果知道某個時刻的出現次數 \(k\),那麼貢獻即為 \(C_k^2\),即取兩個時刻作為左右端點的方案數。
所以我們可以以左端點為 \(1\) 跑一次模擬,把每個時刻的棧都存起來,這個過程可以用雜湊實現,再放到 map 中記錄次數,set 存有多少種雜湊值。
可以看出,跑一次模擬可以找到所有可消除子串的左右端點。
如果用 unordered_map,複雜度為 \(O(n)\)。
總結:沒有發現關鍵性質,轉化貢獻的計算。