Codeforces Round #712 (Div. 2) F. Flip the Cards 思维 + 贪心
傳送門
文章目錄
- 題意:
- 思路:
題意:
給你nnn張卡片,每張卡片正面寫有數字aaa,反面寫有數字bbb,[1,2?n][1,2*n][1,2?n]之間的整數在這些數字中都恰好出現一次,我們認為這nnn張牌是排好序的當且僅當ai<ai+1,bi>bi+1a_i<a_{i+1},b_i>b_{i+1}ai?<ai+1?,bi?>bi+1?,你現在有兩種操作:
(1)(1)(1)將第iii張牌翻過來。
(2)(2)(2)重新排序nnn張牌,順序任意。
問最少需要翻幾次牌,或者無解。
思路:
首先如果存在一個位置的ai<n,bi<na_i<n,b_i<nai?<n,bi?<n,那么由鵲巢原理可知,一定存在某一位置ai>n,bi>na_i>n,b_i>nai?>n,bi?>n,這兩個牌的位置不管怎么牌都不符合要求,這種情況無解。
之后我們考慮將[1,n][1,n][1,n]都翻到正面,之后設f(i)f(i)f(i)表示與iii卡片對應的數。之后我們就將卡牌轉換成了(i,f(i))(i,f(i))(i,f(i))這樣的形式。目前我們保證了正面的iii是遞增的,反面是不確定的,答案一定是將某些牌翻面,讓后放在最后面,因為反面之后[1,n][1,n][1,n]的數到反面,一定小于[n+1,n?2][n+1,n*2][n+1,n?2],且反面之后還需要將其reversereversereverse一下,因為在正面是升序,反面應該降序。這樣就需要對我們的f(i)f(i)f(i)有要求了,先給出結論:能將f(i)f(i)f(i)分成至多兩個單調下降子序列的時候才有解。 我們觀察一下上面說的情況,在翻面之后,翻面之后還反面的肯定是需要單調遞減的,而翻到正面的由于我們需要reversereversereverse一下, 在reversereversereverse之后需要遞增,那么原來也需要遞減,所以結論成立。
現在問題就變成將f(i)f(i)f(i)分成至多兩個單調遞減的子序列,這個是個經典貪心問題,直接用兩個棧,當小于某個棧的時候直接放進去就好了。但是這個題需要翻最少的次數,我們怎么才能保證是最優解呢?題解有一個很妙的方法,就按照minj<=if(j)>maxj>if(j)min_{j<=i} f(j) > max_{j>i} f(j)minj<=i?f(j)>maxj>i?f(j)分成若干段,即在i,i+1i,i+1i,i+1之間加一塊隔板,就可以將這幾段分成若干個子問題,這幾段滿足如下兩個性質:
(1)(1)(1)每段都相互獨立
(2)(2)(2)每段內的劃分方案是唯一的。
獨立是比較容易想到的,因為保證了minj<=if(j)>maxj>if(j)min_{j<=i} f(j) > max_{j>i} f(j)minj<=i?f(j)>maxj>i?f(j),所以每兩段答案一定是可以接在一起的。
方案唯一性的證明想了好長時間也沒想明白,就不說了。
這樣的話對于每一段,維護兩個棧,貪心的選就好了。
總結
以上是生活随笔為你收集整理的Codeforces Round #712 (Div. 2) F. Flip the Cards 思维 + 贪心的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces Round #71
- 下一篇: 人虫大战攻略