标签:its 数字 pre 第一个 ORC namespace card test 不能
一共有2*n张牌,n张0,n张1到n。现在随机的n张(有0有数字)在手上,另n张再牌堆中,现在已知手上的牌和牌堆的牌,可以进行多次以下操作:将手中任意一张牌放入牌堆底,将牌堆顶的一张牌放入手中。问最少多少次后可使牌堆顶到牌堆底的n张牌分别为1,2,3...n。
首先,要完成最后的状态,可以每次都放0,直到所有数字都在手上(因为0的张数与数字的张数都是n,所以一定可以用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 }
标签:its 数字 pre 第一个 ORC namespace card test 不能
原文地址:https://www.cnblogs.com/LiqgNonqfu/p/10990238.html