CSP模擬賽 #42

Lgx_Q發表於2024-10-22

#40 懶得寫了,#41 題目質量過低。

A

\(n\) 張長度為 \(m\) 的紙條,每張紙條有 \(k_i\) 個位置有小寫字母,其他位置透明。你需要合理從上到下排列這些紙條,使得最終在上方看到的字串為 \(s\),保證對於每個位置,至少一張紙條在該位置有一個字母。給出方案或無解。

\(1\le n,m\le 10^5, \ \sum k_i \le 2\times 10^5\)

紙條用的越多越好,這是一個類拓撲排序。提取出每張紙條被限制的位置,每放上一張紙條就把所覆蓋的位置全標記一下,解放這些位置。對於每張紙條,記錄一個 \(cnt_i\) 表示剩餘仍被限制住的位置數,把 \(cnt_i = 0\) 的紙條加入佇列。

B

給定兩個序列 \(a_{1\dots n}, \ b_{1\dots m}\)。你需要分別選擇 \(a\)\(b\) 中一段,滿足選出的兩段長度相等,並且兩個子段對應位置上的數相加後是一個迴文序列。求最長的迴文序列。

\(1\le n, m \le 10^5\)

設提取出來的子段為 \(A,B\),那麼 \(A+B = (A+B) ^ R \Rightarrow A - A^R = B^R - B\)。處理出 \(a,b\) 兩個序列以及 reverse 後的序列的雜湊值即可 \(\mathcal O(1)\) 判斷。

迴文序列有奇偶兩種,對於奇偶兩種都做一次二分,轉化為判定 \(mid\) 是否合法。

提取出 \(a,b\) 的所有長度為 \(mid\) 的子段,扔進雜湊表裡判斷一下是否有相同的即可。

  • 啟示:每一步思路清晰。

C

一個長度為 \(n\) 的排列,有若干個位置未填寫。你需要填寫這些位置,求出最大的 LIS。

\(1\le n\le 10^5\)

\(p_i\) 為前 \(i\) 個位置中未填寫的位置個數,\(q_i\)\(1...a_i\) 中未出現的數字個數,那麼 \(f_i = \max\limits_{j = 1} ^ {i - 1} \{f_j + \min(p_i - p_j, q_i - q_j)\}\),cdq 分治即可。

D

一個值域為 \([1, n]\) 的整數序列 \(a_{1\dots n}\),滿足每種整數最多出現 \(2\) 次。設 \(S[l, r]\)\(a_{l\dots r}\) 組成的可重集,設 \(T\) 為所有 \(S[l, r]\) 組成的集合,求 \(\text{card}(T)\)

若一個區間 \([l, r]\),存在另一個區間 \([l', r']\) 滿足 \(l' < l\)\(S[l, r] = S[l', r']\),那麼不合法,考慮用 \(\frac {n(n + 1)}2\) 減去所有不合法的區間。

一個區間 \([l, r]\) 不合法,當且僅當滿足以下之一:

  • 存在 \([l', r']\) 滿足 \(r' < l\)\(S[l', r'] = S[l, r]\)

  • 存在 \(l\le l'\le r\),滿足 \(S[l', r] = S[l - (r - l' + 1), l - 1]\)

\(b_i\) 為前一個等於 \(a_i\)\(a_j\) 的位置 \(j\)。若不存在,則 \(b_i = -2i\),設 \(c_i = \max(0, b_i)\)

條件一很好算,令 \([b_i, c_i]\) 為區間,考慮單調棧 + 線段樹維護最小值個數。

條件二可以列舉 \(l'\),維護 \(r\) 的資訊。設 \([l', r]\) 這一段的 \(c_i\) 的最大值為 \(p_r\),那麼區間 \([l = p_r, r]\) 有貢獻。一個區間可能貢獻多次,我們強制令每個 \(r\) 透過最大的 \(l'\) 來貢獻。具體的,在每個 \(r\) 上維護一個標記。\(r\) 位置上統計的最小值為 \(0\) 且有標記,去除標記並對答案造成貢獻。當 \(p_r\) 改變時,對應貢獻到的區間會改變,所以應重新給這些 \(r\) 打上標記。

我們需要動態求出所有最小值的位置上的標記,去除所有最小值位置上的標記,或者給一段位置重新打上標記,這些都可以用線段樹解決。

減去同時滿足條件一和條件二的情況,這種情況只可能是 \(l' = l\)。考慮求出滿足 \(p_r = l' - 1\)\(r\) 的區間 \([r_0, r_1]\),貢獻為這一段區間中最小值為 \(0\) 的位置的標記個數。

啟示:更換列舉物件(列舉 \(l'\));最小表示法;容斥拆條件

相關文章