SEERC 2020 題解


啥都想不到

A - Archeologists

考慮一個 naive dp:\(f_i(j)\) 表示第 \(i\) 個位置,深度為 \(j\) 的最大收益。那么:

\[f_{i}(j) = \max\{f_{i-1}(j-1),f_{i-1}(j),f_{i-1}(j+1)\} + j\times p_i \]

然后這沒法直接優化,不過這個 \(f_i\) 其實是凸的。

證明可以用一個轉化:對位置 \(\{1, 2, \cdots, n-1, n\}\) 這些位置做線段覆蓋,線段左右端點必須為 \(1\sim n\) 的整點。一個點被覆蓋的次數為 \(c_i\),則答案為 \(\sum_{i}c_ip_i\)。附加條件:每個點被作為起點或重點至多一次。

用流表示選中一段區間——這樣使入邊和出邊容量為一即可控制這個附加條件。首先設 \(s_i=\sum_{j\le i} p_i\),考慮對於點 \(0, 1, 2, \cdots, n-1, n\),源匯點分別為 \(S,T\),如下建圖:

  • \(i\to i+1\),容量無限,費用為 \(0\)
  • \(S\to i\),容量為一,費用為 \(-s_i\)
  • \(T\to i\),容量為一,費用為 \(s_i\)

答案即為最大費用最大流,其凸性還是比較顯然的,那么 \(f_i\) 也是凸函數了。

如何維護 \(f_i\)​?我們可以開一顆平衡樹,支持全局查最值(的位置),等差數列加。具體實現還有不少細節,我也沒寫過。\(O(n\log n)\)​ 已經可以通過了。

有趣的是,我們建好了費用流模型,使用模擬費用流的思想就能解決問題。考慮從右往左,用一個堆維護一個后綴的出邊。然后用當前位置的入邊去匹配一條最大的。由於不是每條邊都需要選擇,我們不妨每個位置入堆兩次,最后總共的貢獻中會有一次抵消(一個方案中 \(a\to b\)\(b\to c\) 的值相當於 \(a\to c\))。這個做法好寫很多。其實就是帶悔貪心。

B - Reverse Game

只要想到逆序對這個關鍵切入點就勝利了。記逆序對數為 \(I\)

考慮這些操作這么設置的本質,就是可以使 \(I\) 一次減少 \(1\) 或者 \(2\)(保證逆序對 \(\ge 0\))。如果要使 \(I\) 減一那么必然存在一個 \(\texttt{10}\) 子串,翻轉即可減一。如果 \(I>1\) 時需要減二,那也必然存在剩下三種子串之一。具體可以用反證法簡單證明。

\(O(n)\) 計算 \(I\),對於 \(I\in\{1, 2\}\) 是先手必勝,\(I=3\) 則后手必勝。根據必勝-必敗態定理易得 \(I\in \{4,5\}\) 是先手勝,\(I=6\) 后手……因此 \(I\bmod 3 = 0\) 時輸出 Bob,否則輸出 Alice

D - Disk Sort

考慮一個思考方向:每次花費 \(\le 6\) 次操作排好一個顏色。

根據直覺,每次我們一定是選擇“移除目標顏色圓盤上的圓盤數盡可能少”的顏色,這樣我們清理上方比較方便。

對與一種顏色,設 \([a, b, c]\) 表示其三個位置的深度(由上到下深度依次為 \(0,1,2\))。注意到一個顯然的結論,就是一定存在一個 \([a, b, c]\) 使得 \(a+b+c\le 3\)。而除 \([1,1,1]\) 外的所有這樣的情況都可以通過不超過 \(6\) 次操作,得到一個新的排好序的柱子。

以上一共 \(5\) 中情況,都可以手模驗證。然而我們發現除去 \([1,1,1]\) 並沒有影響,因為總會存在一個顏色是滿足至少一個圓盤在頂上。

如果每次都找一個這樣的顏色,將其排序,一共需要 \(6(n-1)\) 次(最后一種顏色會在最后天然排好)。最后花費 \(3\) 次將最后一個柱子清空。

復雜度 \(O(n^2)\),實現非常有技巧性。如果不想寫長,可以考慮 \([a, b, c]\) 應滿足 \(a \le 0, b\le 1\)。這樣可以快速方便地找到可操作的顏色。我們目標明確地將目標圓盤都移到空柱子上,然后記錄一下除空柱子外的空位就能簡單地移除上方的障礙了。這樣還不用考慮兩個目標圓盤在同一個柱子上的情況。

參考實現(參考 hellomath):https://codeforces.com/gym/103102/submission/128966492

E - Divisible by 3

\(s(l,r)=\sum_{i=l}^r a_i\)

考慮有 \(w(l,r) = w(l,k) + w(k+1,r) + (s_{k}-s_{l-1})\times (s_{r}-s_{k})\),這個東西很好拆,差分統計。

將左端點集合按前綴和以及前綴的 \(w\) 值按 \(\bmod 3\) 分類。然后就 \(O(n)\) 了。

F - Fence Job

考慮從合法的結果入手而不是操作,因為不同的操可能得到相同的結果。對於一個 \(h_i\),它可以通過操作“擴展”,從而對區間 \([l,r]\) 賦值,其中 \([l,r]\) 是極長的包含 \(i\) 的,滿足最小值為 \(h_i\) 的區間。

動態規划,定義 \(f(i,j)\)​​​ 為只使用 \(h_{1\sim i}\)​​​,構造一個長度為 \(j\)​ 的結果序列的方案數。考慮從 \(f(i, \cdot)\)​ 轉移到 \(f(i+1, \cdot)\)​。設 \([l,r]\)​​​ 為其極大拓展區間,那么寫出轉移:

\[\forall j\in [l,r],\qquad f(i+1,j) = \sum_{k=l-1}^j f(i,k) \]

通過顯然的前綴和優化,這個式子已經可以 \(O(n^2)\) 算出了。實現時可以將第一維滾掉。

H - AND = OR

由於與操作不會變大,或操作也不會減小。那么我們定義一個指標,使得按照一個中間指標將區間中的數划分開,“大”的在一組,“小”的在另一組。大的用與運算,小的用或運算。然后直接判斷。

直接按數值大小作為指標划分是滿足條件的,然而不能直接枚舉,復雜度會出問題。而還有一個滿足條件的指標則是二進制中一的個數,相比之前的枚舉量只有 \(30\)

考慮一個詢問 \([l,r]\),枚舉中間指標 \(k\),使得二進制中一的個數 \(<k\) 的在第一組,\(>k\) 的在第二組。而 \(=k\) 的,可以放在任意一邊。值得注意的是,如果 \(=k\) 中的數全部相等並且個數超過 \(1\),還可以分到兩邊。

使用線段樹離線處理即可(好像可以開 \(30\) 棵線段樹也行?)。復雜度 \(O(n\log n\log a)\),實現比較比較復雜,注意常數。

Update 2021/10/20:更新一個單 \(\log\) 分治做法:https://codeforces.com/blog/entry/90956?#comment-852344

I - Modulo Permutations

網上題解不清不楚,還是萬老爺靠譜。

切入點:對於任意一個數 \(x\),將它放在 \(1\)\(2\) 的左側或右側都是合法的。而對於其他相鄰昂貴的兩數 \(a,b\),則 \(a>b\) 是必要(不充分)條件。

問題轉化為,將 \(3\sim n\) 分為兩組數 \(A,B\),使得 \(A,B\) 降序排序后滿足條件。一下以“1-段”和“2-段”簡稱。由於是降序,我們不妨從 \(n\) 考慮到 \(3\)。顯然有 naive 的 dp:\(f(x,i,j)\) 表示放置數字 \(x\sim n\),1-段末尾為 \(i\),2-段末尾為 \(j\) 的方案數。一個顯然的優化是,\(i,j\) 中必有一個 \(x\)。於是令 \(f(x,i)\)\(x\sim n\) 中,\(x\) 在 1-段末尾,\(i\) 在 2-段末尾。那么有轉移:

\[\begin{aligned} f(x,i) &\to f(x-1,i) & (x,x-1)\text{合法}\\ &\to f(x-1, x) & (i,x-1) \text{合法} \end{aligned} \]

第一個轉移比較平凡,\((x,x-1)\) 必然合法,相當於將數組復制了一遍。索性忽略它,直接略去第一維。而第二種轉移總數是調和級數級別的,直接枚舉 \(x-1\) 的倍數 \(+0,1,2\) 即可。復雜度 \(O(n\log n)\)

J - One Piece

像這種 observation 題是真不會……

一個顯然的事情就是,如果對於一個點,存在另一個點的最遠距離小於這兩點間的距離,那概率就是 \(0\)。那么我們考慮先將這些點剔除,看似需要對每個點跑一遍 dfs,實際上只要對最遠距離最小的點操作一次就行了。

然后對於剩下的部分,考慮必然存在一對關鍵點形成的路徑為直徑。那么有,這個直徑的中點必然是上述那個最小點,記為 \(x\)。或兩個最小點間的邊,這種情況討論一下即可,暫且略過)。於是跑出每個點到 \(x\) 的距離,除了距離最大的那些點之外概率都是 \(1/2\)

然后對於這些最大點,我們按其所屬 \(x\) 的子樹分類。可以發現,如果一類中點數較少,那么其中每個點分配到的概率就越大。所以具體算不清楚沒關系,不過可以確定的是必然 \(>1/2\)

求解就先輸出最大點,輸出時按所屬類大小排序即可。然后輸出 \(1/2\) 的點,最后輸出剔除的點。

L - Neo-Robin Hood

考慮如果我們已經暫時選定了兩個集合 \(A, B\)​,代表我們的策略是“偷 \(A\)​ 買 \(B\)​”(顯然要保證 \(|A|=|B|,A\cap B=\varnothing\)​)。這並不決定最終策略,於是調整。對於一個 \(x\in A\) 以及一個 \(y\in B\),如果“偷 \(x\)\(y\)”比“偷 \(y\)\(x\)” 更劣,那必然會交換他們。我們把條件寫出來:\(m_x-p_y<m_y-p_x\)。由於這個不等式的兩邊都涉及到了 \(x,y\),不好那么好操作。而經過移項,可得 \(m_x+p_x<m_y+p_y\)。我們設 \(val_x=m_x+p_x\) 作為排序的指標。

我們按 \(val\)​​ 降序排序。考慮一個最終的策略 \(A, B\)​​,必有 \(\max(A)<\min(B)\)。顯然一旦違反這個性質就可以做一些交換,小的編號換到 \(A\),大的換到 \(B\),可以發現新的策略必然優。

上面的性質促使我們將這個數組分為兩段,\([1: i]\) 以及 \([i+1:n]\),分別代表 \(A,B\) 的選取范圍。維護 \(A\) 使用大根堆,維護 \(B\) 使用小根堆。順序完成 \(1\sim n\) 中所有的 \(i\) 即可。不過似乎不太好同時控制兩邊的選取個數,當如果限定選 \(k\) 個卻簡單了。

二分答案。注意到答案 \(k\) 有單調性。如果選 \(f\) 個可行,那 \(f-1\) 必然可行。總復雜度 \(O(n\log^2 n)\)。​

M - Mistake

考慮一個有趣的貪心:對於當前的 \(x\),將它加入到編號盡量小的當中去。具體的,對每個 \(i\in[1, n]\) 維護一個集合 \(S_i=\{1, 2, \cdots, k-1,k\}\),每次找到 \(S_x\) 中的最小值輸出並刪除。也就是說,輸入的圖白給了。

給個非常感性的說明,按照這樣的策略,越小的編號,其已經構造完的答案“越完善”。如果出鍋了實際上就是無解了。復雜度可以做到 \(O(nk+m)\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM