CF 1173C Nauuo and Cards
Posted liqgnonqfu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 1173C Nauuo and Cards相关的知识,希望对你有一定的参考价值。
题目大意
一共有2*n张牌,n张0,n张1到n。现在随机的n张(有0有数字)在手上,另n张再牌堆中,现在已知手上的牌和牌堆的牌,可以进行多次以下操作:将手中任意一张牌放入牌堆底,将牌堆顶的一张牌放入手中。问最少多少次后可使牌堆顶到牌堆底的n张牌分别为1,2,3...n。
思路
首先,要完成最后的状态,可以每次都放0,直到所有数字都在手上(因为0的张数与数字的张数都是n,所以一定可以用0把所有数字都换出来),再依次放入牌堆。
可以减少次数的地方有两个:
- 有些牌直接在牌堆里就可以,不用再手中倒一下。(例如,原题中的第一个例子,1在所有操作时都在牌堆中。)
- 不一定要等到所有的牌都在手中才开始按顺序放入牌堆,也就是说,换出 i 不一定全用0。
第一个,我可能没想到什么好方法,特殊讨论一下,看能不能直接放完。
第二个,最终放入堆底牌的顺序一定是 0,···,0,1,2,···,n,因此关键是考虑有多少个0。计算出每张数字牌换到手中本来需要的0的张数p[i],这些0中最多有i-1个都能变成数字,因此要使得 i 在开始放数字时顺利,就最少需要放 p[i]-i+1 张0。所以,找出放0最多的,再加n就好。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int shou[200005],dui[1000006],hd,tl,ans,p[200005],n,inshou[200005]; 6 7 bool paixu() 8 9 bool ret=1; 10 for(int i=1;i<=n;i++) 11 12 if(i!=dui[i+hd])ret=0; 13 14 return ret; 15 16 17 void workp() 18 19 for(int i=1;i<=n;i++) 20 21 p[shou[i]]=0; 22 23 for(int i=1;i<=n;i++) 24 25 p[dui[i]]=i; 26 27 return ; 28 29 30 int main() 31 32 scanf("%d",&n); 33 for(int i=1;i<=n;i++) 34 35 scanf("%d",&shou[i]); 36 inshou[shou[i]]++; 37 38 for(int i=1;i<=n;i++) 39 40 scanf("%d",&dui[i]); 41 42 hd=0;tl=n; 43 while(inshou[dui[tl]+1]) 44 45 ans++; 46 tl++; 47 dui[tl]=dui[tl-1]+1; 48 inshou[dui[tl]]--; 49 hd++; 50 inshou[dui[hd]]++; 51 52 if(paixu()) 53 54 printf("%d\n",ans); 55 return 0; 56 57 else 58 59 ans=0; 60 workp(); 61 for(int i=1;i<=n;i++) 62 63 ans=max(ans,p[i]-i+1); 64 65 ans+=n; 66 67 printf("%d\n",ans); 68 return 0; 69
以上是关于CF 1173C Nauuo and Cards的主要内容,如果未能解决你的问题,请参考以下文章