這里是 Codeforces Round #743 (Div. 2) 的解題報告 qwq,這是一場 Div. 1 和 Div. 2 的比賽,然而這次 Div. 1 出現了計算幾何,然而我因為沒有學過計算幾何而導致止步於 Div. 2。本場比賽時評測機宕機了,導致比賽 unrated,即便如此,本次的題目的亮點仍然是不容忽視的。
到 2021/9/24 為止,筆者並沒有想出 CF1572C. Paint 中區間 dp 正確性的證明,所以該題題解只能咕咕咕。
update:CF1572C 請教學長后得到了一個比較感性的證明,寫在這里。
CF1573A. Countdown
Description
給定一個 \(n\) 位的十進制數,每次你可以交換任意兩位數或者將其減 1,問最少多少次操作可以使其變為 0。多組數據。
數據范圍:\(1 \leq t \leq 10^3, 1 \leq n \leq 100.\)
Solution
比較容易想出的一個貪心策略是先將個位清 0,然后在再將各個非 0 位上的數換到個位減掉即可。考慮貪心的正確性,如果將個位清 0 后繼續減 1,會使最少增加一位 9 而只使較高的一位減少 1,很容易發現這樣做是不優的。
Code
CF1573B. Swap
Description
給定長度均為 \(n\) 的 \(\{a_n\},\{b_n\}\) 兩個序列,\(\{a_n\}\) 包含 1 到 \(2n\) 中所有的奇數,\(\{b_n\}\) 包含 1 到 \(2n\) 中所有的偶數,你每一次可以選擇一個序列中相鄰的兩個位置,交換這兩個位置上的數,問最少需要多少次交換可以使得 \(\{a_n\}\) 的字典序小於 \(\{b_n\}\),多組數據。
數據范圍:\(1 \leq t \leq 10^4, 1 \leq \sum n \leq 10^5\)
Solution
一個有趣的事實是,由於兩個序列的元素交集為空,所以字典序的比較只需關注 \(a_1 < b_1\) 是否成立即可。所以我們可以考慮枚舉每一個 \(a_i\) 看將其交換到 1 位置后讓一個在序列 \(\{b_n\}\) 中,離 1 位置最近的滿足 \(b_k > a_i\) 的 \(b_k\),為了快速找到這個 \(b_k\) 的位置,我們只需維護一個后綴最小值 \(pos_i\) 表明在 \(\{b_n\}\) 中排名第 \(i\) 到第 \(n\) 的數的最小位置即可。
Code
CF1572A. Book
Description
有一本 \(n\) 個章節的書,每一個章節都需要在閱讀所有其要求的前置章節后,才被可以讀懂,一開始你不能理解任何一個章節,每一次你都會依次閱讀第 1 章到第 \(n\) 章,遇到無法讀懂的章節,就直接跳過。如此一遍遍重復直到你理解了所有章節。問理解所有章節所需要的最小閱讀次數,如果無論閱讀多少次都不能理解所有章節,則輸出 -1,多組數據。
數據范圍:\(1 \leq t \leq 2 \times 10^4, 1 \leq \sum n \leq 2 \times 10^5.\)
Solution
首先考慮如何判斷有無解,顯然有解的充要條件是給定的限制關系的圖一定是一張 DAG。考慮如何求出最小的閱讀次數,為了方便,我們讓邊 \(u \rightarrow v\) 表明章節 \(v\) 為章節 \(u\) 的前置章節。我們發現一條邊 \(u \rightarrow v\) 對答案有貢獻當且僅當 \(u < v\) 成立,這是因為我們是按照升序閱讀各個章節的。
所以我們考慮在 DAG 上記憶化搜索,設 \(dp(u)\) 為理解 \(u\) 這個章節需要的閱讀次數,根據上面的分析,我們有:
最終最大的 \(dp(u)\) 即為所求。
Code
CF1572B. Xor of 3
Descripiton
給定一個長度為 \(n\) 的 01 序列 \(\{a_n\}\),每次你可以選擇相鄰的三個位置 \(a_i, a_{i + 1}, a_{i + 2}\,(i \in [1, n - 2])\),將三個位置上的值均修改為 \(a_i \oplus a_{i + 1} \oplus a_{i + 2}\),其中 \(\oplus\) 為異或運算。給出一個不超過 \(n\) 次操作的操作序列,使序列中所有值變為 0,或者報告這是不可能的。多組數據。
數據范圍:\(1 \leq t \leq 10^4, 3 \leq \sum n \leq 2 \times 10^5.\)
Solution
經過驗算可知,當且僅當 \(a_i, a_{i + 1}, a_{i + 2}\) 有恰有兩個或沒有一個是 1 時,這時異或值才為 0,否則這個異或值只能為 1。所以我們考慮這樣一種策略,在掃到一個非 0 的位置 \(j\) 時,如果從這位置開始的三個數中有兩個是 1 就直接將三個數變為 0,否則全部變為 1 並且讓 \(j + 2\) 也做同樣的判斷。顯然,這樣做最終會使序列變成前面一段連續的 0 和后面一段連續的 1,也有可能得到全 1 串和全 0 串。我們發現現在就很容易判斷當前串是否合法,只需按此方法再掃一遍,判斷最終是否可以變為全 0 串即可。
我們發現,由於每次更改操作都會間隔 1 個位置,且序列的最后兩個位置不可以選,所以掃描一次最多產生 \(\lceil \frac {n - 2} {2} \rceil\) 次操作,故兩次掃描的操作的序列的長度也不會超過 \(n\),所以這樣得出的答案總是合法的。
Code
CF1572C. Paint
Description
給定一張由 \(n\) 個像素所組成的圖片,其中第 \(i\) 個位置的顏色是 \(a_i\),每一次你可以將一段連續的塗有相同顏色的顏色段塗成其他顏色。問最少需要塗色多少次可以將整個圖片塗成一種顏色。多組數據。
數據范圍:\(1 \leq t \leq 10^3, 1 \leq \sum n \leq 3 \times 10^3, 1 \leq a_i \leq n.\)
數據保證對於初始的圖片,每種顏色出現的次數最多為 20.
Solution
我們不妨設 \(f(i, j)\) 表明區間 \([i, j]\) 塗成一種顏色的最小染色次數。我們可以發現對於區間 \([i, j]\),一定有一個最優方案使得整個區間最后染成 \(a_j.\) 這是因為 \(j\) 在區間 \([i, j]\) 的邊緣,一定存在一個 \(k \in [i, j - 1]\),使得先將 \([k, j - 1]\) 染成一個顏色,后將 \([k, j]\) 統一顏色,再將整個區間 \([i, j]\) 染成同一顏色。若 \([k, j - 1]\) 按照一種最優方案染完色后與 \(a_j\) 的顏色不同,則要使整個區間顏色相同,只需讓 \(j\) 或 \([k, j - 1]\) 整體變顏色,無論變成什么顏色,必然需要使用一次染色,故選擇將區間 \([k, j]\) 染成 \(a_j\) 是不劣的,而同理將區間 \([i, k - 1]\) 和 \([k, j]\) 的顏色統一時,都將他們染成 \(a_j\) 也是不劣的。
所以我們可以將 \(f(i, j)\) 重新定義為,將區間 \([i,j]\) 塗成 \(a_j\) 時的最小染色次數。則有:
而這樣轉移是 \(O(n^3)\) 的,顯然會超時。我們發現題目中 “每種顏色出現次數最多為 20” 這個性質我們沒有應用,進一步考慮,我們發現區間 \([i, j]\) 的決策點 \(k\),總存在一個決策點有 \(a_k = a_j\) 的性質。這里給出一個感性證明,我們考慮將 \([i, j]\) 這個區間按照 \(a_k = a_j\) 划分成若干小區間 \([i, k_1], [k_1 + 1, k_2], \cdots, [k_m + 1, j]\) 顯然這些區間合並時不需要額外使用一次染色的機會,而如果再將其中一個區間拆開作為決策點,那么會少一次將左半部分染成 \(a_j\) 的操作,會多出一次將決策點左右兩部分顏色統一的染色操作,所以這樣做是不劣的。故我們枚舉決策點時,只需枚舉 \(a_k = a_j\) 的那一部分即可。這樣時間復雜度為 \(O(20 \cdot n^2)\),即 \(O(n^2)\)。
Code
CF1572D. Bridge Club
Description
一場比賽有 \(2^n\) 個預選參賽者,它們從 0 到 \(2^n - 1\) 編號。其中第 \(i\) 名參賽者如果參賽,則其支付的錢數為 \(a_i.\) 比賽要求以兩個人組隊的形式參加,最多可以有 \(k\) 個隊伍。兩名參賽者願意組成一個隊伍當且僅當兩名參賽者的編號的在二進制中僅有一位不同。求比賽承辦方最多可以收到多少錢。
數據范圍:\(1 \leq n \leq 20, 1 \leq k \leq 200, 1 \leq a_i \leq 10^6.\)
Solution
本題可以轉化為一個費用流模型,我們首先發現當 \(k > 2^{n - 1}\) 時,我們可以至多分成 \(2^{n - 1}\) 組,所以下文的 \(k\) 均為 \(\min(k, 2^{n - 1})\),又發現如果兩名參賽者可以在一個隊中,則他們編號的二進制表示中 1 的個數的奇偶性一定是不同的。所以我們可以按照奇偶性的標准將參賽者分為兩類。考慮費用流的建圖,我們建圖只需先從源點向輔助點先連一條流量為 \(k\),費用為 0 的邊,然后再從輔助點向其它已經分好類的一類點各連一條流量為 1,費用為 \(a_i\) 的邊,兩類點之間將可以在一個隊中的點連一條流量為 1,費用為 0 的邊,然后在令所有另一類點向匯點連一條流量為 1,費用為 \(a_i\) 的邊。建完圖后跑最大費用最大流即可。
但這樣建圖有一個問題,我們發現點和邊的數量均過多,我們難以承受。但是我們發現,我們按位考慮,將每一個參賽編號為 \(i\) 的參賽者與其二進制位在第 \(j\) 位不同的參賽者組成的隊所支付的錢數進行排序,然后取前 \(2k\) 個參賽者即可。這樣點和邊的數量就被縮小在了 \(O(nk)\) 的級別上,這個圖和二分圖較為相似,故使用 Dinic 算法實現的費用流的復雜度大約只有 \(O((nk)^{1.5})\),可以通過本題。
